Skip to content

V/2.0 dev#28

Merged
dgtlss merged 4 commits into
mainfrom
v/2.0-dev
Jul 14, 2026
Merged

V/2.0 dev#28
dgtlss merged 4 commits into
mainfrom
v/2.0-dev

Conversation

@dgtlss

@dgtlss dgtlss commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

Warden 2.0 refocuses the package as a deterministic, CI-first security gate for Laravel applications.

This release introduces typed audit contracts, dependable exit codes, parser-backed source analysis, supply-chain protections, governed suppressions and baselines, machine-readable reports, safe CI initialization, and a substantially clearer console experience.

What changed

Dependable CI security gates

  • Added typed Finding, AuditResult, AuditError, AuditReport, and AuditContext objects.
  • Established deterministic exit codes:
    • 0 — scan completed without findings meeting the failure threshold.
    • 1 — blocking findings met --fail-on.
    • 2 — incomplete scan, invalid configuration, scanner failure, timeout, or malformed output.
  • Replaced --severity with --fail-on.
  • Added explicit ci, production, and local profiles.
  • Added production and all-dependency scopes.
  • Audit exceptions are isolated and represented in the final report.
  • Machine output remains valid and free from progress messages.

Application source scanning

Added a default parser-backed source audit using PHP-Parser and Symfony Finder.

Coverage includes:

  • Provider credentials and private keys.
  • Dynamic raw SQL.
  • Tainted command execution.
  • Unsafe deserialization.
  • SSRF destinations.
  • Filesystem path traversal.
  • Open redirects.
  • Raw output and XSS sinks.
  • Disabled TLS verification.
  • Deprecated ciphers.
  • Explicit CSRF middleware removal.
  • Unescaped Blade output.
  • Missing Blade CSRF directives.
  • Disabled mass-assignment protection.
  • Debug calls.
  • Sensitive logging.
  • Contextual weak hashing and insecure randomness.

PHP files are parsed once and analysed using lightweight intraprocedural taint tracking. Credentials are always redacted and contribute only a one-way hash to fingerprints.

Unreadable, oversized, or unparseable selected files mark the scan incomplete and return exit code 2.

Composer, npm, and supply-chain auditing

  • Composer audits use the lockfile and default to production dependencies.
  • npm is automatically audited when package-lock.json is present.
  • Added checks for:
    • Missing or stale lockfiles.
    • Insecure Composer repositories.
    • secure-http=false.
    • Overly broad Composer plugin permissions.
    • Unsupported JavaScript lockfiles.
    • Recently released Composer packages.
    • Recently released packages capable of automatic execution.
    • Missing release metadata.
  • Package-age checks operate entirely from lockfile metadata without additional registry requests.
  • Dependency scope can be expanded with --scope=all.

Laravel and platform checks

  • Effective Laravel configuration is inspected instead of relying directly on env().
  • A missing .env is valid in CI.
  • Git determines whether .env is tracked.
  • Added checks for:
    • Application key and cipher.
    • Production debug mode.
    • HTTPS application URLs.
    • Secure, HTTP-only, and SameSite session cookies.
    • Wildcard CORS with credential support.
    • Telescope, Debugbar, and Clockwork in production.
    • Production filesystem permissions.
  • Added an offline platform support calendar for PHP and Laravel.
  • Unsupported versions are blocking; security-only and near-EOL versions are advisory.

Rule policy, suppressions, and baselines

  • Every rule has a stable ID and default disposition.
  • Added rule_overrides with:
    • enforced
    • advisory
    • off
  • Unknown rules and invalid override values fail before scanning.
  • Replaced wildcard suppressions with reviewed entries requiring:
    • id
    • reason
    • expires_at
    • Optional fingerprint
  • Expired or malformed suppressions return exit code 2.
  • Added warden:baseline for explicitly accepting existing fingerprints while continuing to detect new findings.
  • Fingerprints remain stable when unrelated source lines move.

Reports and console output

Added standardized formats:

  • Console
  • Versioned JSON
  • GitHub annotations
  • GitLab dependency scanning
  • SARIF 2.1.0
  • JUnit XML

The console report now provides:

  • A per-check results table.
  • Fixed-width aligned columns.
  • Finding, severity, blocking, advisory, error, and duration counts per check.
  • Dedicated sections for each audit.
  • Severity subsections within each audit.
  • Consolidated repeated findings with occurrence and location lists.
  • Clear incomplete-scan diagnostics.
  • Terminal colours without leaking ANSI sequences into report files.

A versioned JSON schema is included at resources/schemas/warden-report-2.0.0.json.

Safe onboarding

Added:

php artisan warden:init --ci=github|gitlab|both|none

The command:

  • Publishes configuration only when absent.
  • Generates dedicated Warden CI files.
  • Does not overwrite existing application configuration.
  • Does not modify Composer scripts or lifecycle hooks.
  • Allows --force to replace only Warden-owned generated files.

Notifications

  • Consolidated notification delivery through one dispatcher.
  • Notifications are opt-in with --notify.
  • Each channel is invoked once.
  • Delivery failures never change the security exit code.

Removed features

Removed features that conflicted with Warden being a development-only CI dependency:

  • Audit-result caching.
  • Production scheduler.
  • Audit-history migration and configuration.
  • Legacy configuration audits.
  • Duplicate notification paths.

Breaking changes

  • Supported platforms are now PHP 8.3–8.5 and Laravel 12–13.
  • Custom audits must implement:
run(AuditContext $context): AuditResult
  • --severity becomes --fail-on.
  • --output becomes --format.
  • --npm is removed; npm is auto-detected.
  • --force, --no-notify, and warden:schedule are removed.
  • Jenkins JSON is replaced by JUnit XML.
  • Suppressions must include review metadata and an expiry date.
  • Scanner failures now consistently return exit code 2.

See UPGRADE.md for the full migration guide.

CI coverage

The GitHub Actions matrix now covers:

  • PHP 8.3, 8.4, and 8.5.
  • Laravel 12 and 13.
  • Lowest supported dependency resolution.
  • PHPUnit.
  • PHPStan.
  • Rector dry-run.
  • Strict Composer validation.

Validation

  • 49 PHPUnit tests.
  • 233 assertions.
  • PHPStan passes.
  • Rector dry-run passes.
  • composer validate --strict passes.
  • git diff --check passes.

Summary by CodeRabbit

  • New Features
    • Deterministic warden:audit with profile/scope selection, --fail-on, --only/--skip, and machine-readable output to stdout or --output-file.
    • New warden:baseline for expiring JSON baselines and suppression handling.
    • New warden:init to publish configuration and generate GitHub/GitLab CI integration files.
    • Added/updated report formats: console, JSON, GitHub Actions, GitLab, SARIF, and JUnit; notifications can be enabled via --notify.
  • Documentation
    • Updated usage, command changes, supported framework matrix, rule catalogue, and v2 migration guidance.
  • Removed
    • Removed scheduling and audit-history functionality.

dgtlss added 3 commits July 10, 2026 09:07
Rework the package around the new CI-focused audit flow: add typed audit/report value objects, replace the old cache/schedule/history model, introduce baseline and new reporter commands, tighten notifications and suppressions, and update the package metadata/docs for Laravel 12–13 support.
- Introduced new audit types: `platform` and `source`, enhancing security checks.
- Added `nikic/php-parser` and `symfony/finder` as dependencies in composer.json.
- Updated README to reflect new initialization command and audit options.
- Enhanced audit reporting to include blocking and advisory counts.
- Improved configuration options for source paths and supply chain review.
- Added tests for new functionalities and ensured existing tests cover recent changes.
Revamp console output and polish docs. Updates:

- Reworked ConsoleReporter to produce a rich, grouped, and colorized summary (durations, per-check counts, severity breakdowns, locations, remediation, etc.) with helper methods for grouping, wrapping, and formatting.
- ReportFormatterFactory now accepts a decorated flag and passes it to ConsoleReporter.
- WardenAuditCommand improved progress lines, escapes output, and forwards decoration state when building formatters.
- README.md and UPGRADE.md refreshed with badges, intro, and clearer sections.
- Tests updated (ReporterTest) to cover the new console grouping and per-check summaries.

These changes improve CLI readability and ensure ANSI decoration is handled correctly.
@dgtlss dgtlss requested a review from Copilot July 10, 2026 23:40
@dgtlss dgtlss self-assigned this Jul 10, 2026
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4b6ba72f-662d-44af-b8b2-9165fcaafa6e

📥 Commits

Reviewing files that changed from the base of the PR and between 35abf85 and 43b1179.

📒 Files selected for processing (27)
  • .github/workflows/tests.yml
  • docs/rules.md
  • readme.md
  • src/Commands/WardenBaselineCommand.php
  • src/Commands/WardenInitCommand.php
  • src/Commands/WardenSyntaxCommand.php
  • src/Reporters/SarifReporter.php
  • src/Services/AuditRunner.php
  • src/Services/Audits/LaravelConfigAuditService.php
  • src/Services/Audits/PhpSyntaxAuditService.php
  • src/Services/Audits/PlatformAuditService.php
  • src/Services/Audits/SourceAuditService.php
  • src/Services/NotificationDispatcher.php
  • src/Services/RulePolicy.php
  • src/Services/Source/PhpSourceAnalyzer.php
  • src/ValueObjects/AuditReport.php
  • tests/Commands/WardenInitCommandTest.php
  • tests/Commands/WardenSyntaxCommandTest.php
  • tests/Reporters/ReporterTest.php
  • tests/Services/AuditRunnerTest.php
  • tests/Services/Audits/LaravelConfigAuditServiceTest.php
  • tests/Services/Audits/PhpSyntaxAuditServiceTest.php
  • tests/Services/Audits/PlatformAuditServiceTest.php
  • tests/Services/Audits/SourceAuditServiceTest.php
  • tests/Services/NotificationDispatcherTest.php
  • tests/Services/SuppressionServiceTest.php
  • tests/ValueObjects/AuditReportTest.php
💤 Files with no reviewable changes (1)
  • readme.md
🚧 Files skipped from review as they are similar to previous changes (18)
  • docs/rules.md
  • tests/Services/Audits/PlatformAuditServiceTest.php
  • src/Services/Audits/SourceAuditService.php
  • tests/Commands/WardenInitCommandTest.php
  • src/Services/NotificationDispatcher.php
  • tests/Services/SuppressionServiceTest.php
  • src/Commands/WardenBaselineCommand.php
  • .github/workflows/tests.yml
  • tests/ValueObjects/AuditReportTest.php
  • src/Services/AuditRunner.php
  • src/Commands/WardenInitCommand.php
  • src/Services/RulePolicy.php
  • src/Reporters/SarifReporter.php
  • src/ValueObjects/AuditReport.php
  • src/Services/Audits/LaravelConfigAuditService.php
  • src/Services/Audits/PhpSyntaxAuditService.php
  • src/Commands/WardenSyntaxCommand.php
  • src/Services/Source/PhpSourceAnalyzer.php

📝 Walkthrough

Walkthrough

Warden 2.0 replaces stateful audits with typed results, policy-based filtering, structured report formats, new audit and initialisation commands, source and supply-chain analysis, suppression/baseline handling, and expanded CI and documentation.

Changes

Warden 2.0 audit platform

Layer / File(s) Summary
Typed contracts and policy
src/Contracts/*, src/Enums/*, src/ValueObjects/*, src/Services/RulePolicy.php, src/Services/SuppressionService.php, resources/schemas/*
Introduces typed contexts, results, findings, errors, dispositions, suppression validation, and the versioned report schema.
Audit orchestration and commands
src/Services/AuditRunner.php, src/Services/AuditExecutor.php, src/Commands/*, src/Providers/WardenServiceProvider.php
Centralises audit selection and execution, adds baseline and initialisation commands, and updates command registration.
Audit implementations
src/Services/Audits/*, src/Services/Source/*, src/Services/CustomAuditWrapper.php
Refactors audits to typed results and adds configuration, platform, supply-chain, source, taint, and text analysis.
Reporting and notifications
src/Reporters/*, src/Services/NotificationDispatcher.php, src/Notifications/*
Adds structured reporters and centralises notification dispatch and failure handling.
CI, configuration, and documentation
.github/workflows/*, composer.json, src/config/*, src/stubs/*, README.md, UPGRADE.md, docs/*, AGENTS.md, contributing.md, phpstan.neon
Updates compatibility, Composer scripts, CI workflows, generated integrations, configuration guidance, migration documentation, and rule documentation.
Validation coverage
tests/*
Adds coverage for commands, reporters, audits, source analysis, suppression, notifications, policy, and value objects.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • dgtlss/warden#20: Changes the audit command’s execution wiring, options, and notification handling.
  • dgtlss/warden#27: Adds earlier ignored-finding handling that connects to this PR’s suppression-service refactor.

Suggested labels: enhancement

Poem

A rabbit checks each rule in flight,
With typed reports all neat and bright.
CI hops through every lane,
Findings bloom from code and chain.
Warden’s ready—off we go!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.54% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is too vague to describe the changeset and does not tell a teammate what was actually changed. Use a concise, specific title that names the main change, such as CI-first Warden 2.0 audit and reporting overhaul.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch v/2.0-dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR delivers the Warden 2.0 overhaul, refocusing the package into a deterministic, CI-first security gate for Laravel apps with typed audit/report contracts, strict exit codes, new audit coverage (source + platform + supply-chain), and multiple machine-readable report formats.

Changes:

  • Introduces typed value objects (Finding, AuditResult, AuditReport, AuditError, AuditContext) plus a new execution pipeline (AuditRunner/AuditExecutor) with strict exit-code semantics.
  • Adds/updates core audits (source scanning, platform support calendar, supply-chain checks, Laravel config checks, storage checks) and standardized reporters (console/json/github/gitlab/sarif/junit).
  • Adds safe onboarding/ops tooling and docs: warden:init, warden:baseline, UPGRADE guide, rule catalogue, and expanded CI matrix.

Reviewed changes

Copilot reviewed 83 out of 84 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
UPGRADE.md Adds a 2.0 migration guide and highlights breaking CLI/config changes.
tests/ValueObjects/AuditReportTest.php Verifies determinism (ordering/fingerprints) and exit-code behavior.
tests/TestCase.php Introduces a shared Testbench base test case for package tests.
tests/Services/SuppressionServiceTest.php Covers reviewed suppressions, expiry handling, and baseline fingerprint matching.
tests/Services/NotificationDispatcherTest.php Ensures configured notification channels dispatch once.
tests/Services/CompetitorCapabilityTest.php Validates the competitor capability fixture structure.
tests/Services/Audits/SupplyChainAuditServiceTest.php Tests supply-chain findings (composer config, lockfiles, package-age logic).
tests/Services/Audits/SourceAuditServiceTest.php Tests parser-backed source scanning, redaction, overrides, exclusions, and timeouts.
tests/Services/Audits/PlatformAuditServiceTest.php Tests platform support calendar findings and blocking/advisory behavior.
tests/Services/Audits/LaravelConfigAuditServiceTest.php Tests production-vs-ci config checks and expected findings.
tests/Services/Audits/DependencyAuditServiceTest.php Tests composer/npm audit command construction and parsing.
tests/Services/Audits/DebugModeAuditServiceTest.php Removes legacy debug-mode audit tests (feature removed/refactored).
tests/Services/AuditExecutorTest.php Tests exception isolation and invalid result detection in the executor.
tests/Reporters/ReporterTest.php Validates JSON/SARIF/GitLab/JUnit/console output contracts and redaction.
tests/Fixtures/competitor-capabilities.php Adds a capability/disposition fixture for competitive feature mapping.
tests/Commands/WardenSyntaxCommandTest.php Updates syntax command tests to the new typed audit/result model.
tests/Commands/WardenInitCommandTest.php Tests non-destructive init behavior and pinned CI templates.
tests/Commands/WardenBaselineCommandTest.php Tests baseline generation schema and fingerprint capture.
tests/Commands/WardenAuditCommandTest.php Tests deterministic JSON output, fail-on gating, and structured errors.
src/ValueObjects/Finding.php Adds the typed Finding model with stable fingerprinting and JSON shape.
src/ValueObjects/AuditResult.php Adds typed per-audit result container with status/duration.
src/ValueObjects/AuditReport.php Adds typed full-run report with sorting, summaries, and exit-code logic.
src/ValueObjects/AuditError.php Adds typed audit/config error representation.
src/ValueObjects/AuditContext.php Adds typed context (profile/scope/timeout/selection) with validation.
src/stubs/gitlab-ci.yml Adds a dedicated GitLab CI stub for safe onboarding.
src/stubs/github-workflow.yml Adds a pinned GitHub Actions workflow stub for safe onboarding.
src/Services/SuppressionService.php Implements reviewed suppressions + baseline filtering with strict validation.
src/Services/Source/TextSourceAnalyzer.php Adds text-based secret + Blade checks with redaction-safe identities.
src/Services/Source/SourceFileDiscovery.php Adds Finder-based discovery with size/unreadable guards and path validation.
src/Services/RulePolicy.php Adds rule IDs + default dispositions and override validation/application.
src/Services/ReportFormatterFactory.php Centralizes report formatter selection with a strict format map.
src/Services/NotificationDispatcher.php Consolidates opt-in notifications and makes delivery non-gating.
src/Services/CustomAuditWrapper.php Updates custom audit integration to the typed contract.
src/Services/Audits/StorageAuditService.php Refactors storage/deployment checks into typed findings and profiles.
src/Services/Audits/SourceAuditService.php Adds parser-backed source audit orchestration with timeout handling.
src/Services/Audits/PlatformAuditService.php Adds offline PHP/Laravel support calendar audit with blocking/advisory output.
src/Services/Audits/PhpSyntaxAuditService.php Refactors syntax scanning into typed findings via php -l.
src/Services/Audits/NpmAuditService.php Refactors npm audit to lockfile-only mode with typed findings/errors.
src/Services/Audits/LaravelConfigAuditService.php Adds effective-config production checks (env tracked, TLS URL, cookies, tooling, CORS).
src/Services/Audits/EnvAuditService.php Removes legacy env audit (replaced by new config/source approaches).
src/Services/Audits/DebugModeAuditService.php Removes legacy debug-mode audit (replaced by new config checks/tooling rules).
src/Services/Audits/ConfigAuditService.php Removes legacy config audit (replaced by new typed audits).
src/Services/Audits/ComposerAuditService.php Refactors composer audit to locked/no-dev modes with typed findings/errors.
src/Services/Audits/AbstractAuditService.php Removes the old mutable findings base class.
src/Services/AuditRunner.php Introduces the audit selection/validation/orchestration pipeline.
src/Services/AuditExecutor.php Executes audits safely (exception isolation, result validation, duration).
src/Services/AuditCacheService.php Removes legacy audit caching (2.0 is deterministic and CI-first).
src/Reporters/SarifReporter.php Adds SARIF 2.1.0 report generation.
src/Reporters/JunitReporter.php Adds JUnit XML output for CI/test gate integration.
src/Reporters/JsonReporter.php Adds versioned JSON output for machine consumption.
src/Reporters/GitLabReporter.php Adds GitLab dependency scanning output.
src/Reporters/GitHubReporter.php Adds GitHub Actions annotations output.
src/Providers/WardenServiceProvider.php Updates service provider wiring and registers new commands.
src/Notifications/Concerns/HasSeverityHelpers.php Improves typing/docs around notification severity helpers.
src/Notifications/Channels/TeamsChannel.php Makes Teams delivery throw on HTTP failures and adds typing docs.
src/Notifications/Channels/SlackChannel.php Makes Slack delivery throw on HTTP failures; improves reference handling.
src/Notifications/Channels/EmailChannel.php Adds typing docs and keeps email notification behavior aligned.
src/Notifications/Channels/DiscordChannel.php Makes Discord delivery throw on HTTP failures; improves reference handling.
src/Examples/DatabasePasswordAudit.php Updates example custom audit to the new typed audit contract.
src/Enums/Severity.php Adds a typed severity enum with weights + scanner parsing helper.
src/Enums/RuleDisposition.php Adds rule disposition enum (enforced/advisory/off).
src/database/migrations/2024_01_01_000000_create_warden_audit_history_table.php Removes legacy audit-history migration (feature removed).
src/Contracts/ReportFormatter.php Adds report formatter contract for reporters.
src/Contracts/NotificationChannel.php Adds typing docs for notification payloads.
src/Contracts/CustomAudit.php Refactors custom audit contract to run(AuditContext): AuditResult.
src/Contracts/AuditServiceInterface.php Refactors audit contract to typed results.
src/config/warden.php Updates configuration for 2.0: audits, suppressions, baselines, overrides, notifications.
src/Commands/WardenSyntaxCommand.php Refactors syntax command to use typed audit results and exit codes.
src/Commands/WardenScheduleCommand.php Removes scheduler management command (feature removed).
src/Commands/WardenInitCommand.php Adds safe onboarding command for config + CI stub generation.
src/Commands/WardenBaselineCommand.php Adds baseline generation with expiring reviewed entries.
resources/schemas/warden-report-2.0.0.json Adds versioned JSON schema for the 2.0 report contract.
phpstan.neon Tightens static analysis level and aligns exclusions with 2.0 structure.
docs/rules.md Documents rule IDs, defaults, and purpose for governance/overrides.
contributing.md Updates contributor guidance (matrix, toolchain checks, contracts).
composer.json Updates dependencies, dev tooling, scripts, and supported framework matrix.
AGENTS.md Updates agent guidance to match 2.0 commands and support matrix.
.github/workflows/tests.yml Expands CI matrix across PHP/Laravel versions + adds validate/phpstan/rector/lowest deps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Services/Audits/PhpSyntaxAuditService.php Outdated
Comment thread src/Reporters/GitLabReporter.php
Comment thread src/ValueObjects/AuditReport.php

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (14)
src/ValueObjects/AuditReport.php (1)

90-122: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Cache findings() and errors() results in jsonSerialize().

Both methods re-collect (and findings() re-sorts) on every call. jsonSerialize() calls findings() 4 times and errors() 3 times. For reports with many findings, this is wasteful. Storing the results in local variables eliminates the redundant work and improves readability.

♻️ Proposed refactor
     public function jsonSerialize(): array
     {
+        $findings = $this->findings();
+        $errors = $this->errors();
+
         $counts = ['critical' => 0, 'high' => 0, 'medium' => 0, 'low' => 0];
         $blocking = 0;
-        foreach ($this->findings() as $finding) {
+        foreach ($findings as $finding) {
             $counts[$finding->severity->value]++;
             $blocking += $finding->blocking ? 1 : 0;
         }
 
         return [
             'schema_version' => '2.0.0',
             'warden_version' => $this->wardenVersion(),
             'run' => [
-                'status' => $this->errors() === [] ? 'completed' : 'failed',
+                'status' => $errors === [] ? 'completed' : 'failed',
                 'profile' => $this->context->profile,
                 'scope' => $this->context->scope,
                 'scanned_at' => ($this->scannedAt ?? CarbonImmutable::now())->toISOString(),
             ],
             'summary' => [
-                'total' => count($this->findings()),
+                'total' => count($findings),
                 'blocking' => $blocking,
-                'advisory' => count($this->findings()) - $blocking,
+                'advisory' => count($findings) - $blocking,
                 'ignored' => count($this->ignoredFindings),
-                'errors' => count($this->errors()),
+                'errors' => count($errors),
                 'severity' => $counts,
             ],
             'audits' => $this->audits,
-            'findings' => $this->findings(),
+            'findings' => $findings,
             'ignored_findings' => $this->ignoredFindings,
-            'errors' => $this->errors(),
+            'errors' => $errors,
         ];
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ValueObjects/AuditReport.php` around lines 90 - 122, Cache the results of
findings() and errors() in local variables at the start of jsonSerialize(), then
reuse those variables for counting, status determination, summary fields, and
serialized output. Update the foreach, total/advisory counts, run status, error
count, findings, and errors entries to reference the cached results instead of
calling the methods repeatedly.
src/Services/Source/PhpSourceAnalyzer.php (1)

26-50: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Create the PHP parser once and reuse it across files.

A new ParserFactory and parser instance is created for every file on line 29. PhpParser parsers are stateless and safe to reuse. For large codebases this adds unnecessary overhead per file.

♻️ Proposed refactor
 final class PhpSourceAnalyzer
 {
+    private readonly \PhpParser\Parser $parser;
+
     public function __construct(private readonly RulePolicy $rulePolicy)
     {
+        $this->parser = (new ParserFactory())->createForNewestSupportedVersion();
     }

     /** `@return` array{findings: list<Finding>, errors: list<AuditError>} */
     public function analyze(SplFileInfo $file): array
     {
         $path = ltrim(str_replace(base_path(), '', $file->getRealPath()), DIRECTORY_SEPARATOR);
-        $parser = (new ParserFactory())->createForNewestSupportedVersion();

         try {
-            $nodes = $parser->parse($file->getContents());
+            $nodes = $this->parser->parse($file->getContents());
         } catch (Error $error) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Services/Source/PhpSourceAnalyzer.php` around lines 26 - 50, Initialize
and retain a single PhpParser parser instance on the analyzer instead of
creating it inside analyze(). Add a parser property and initialize it once in
the constructor (or equivalent setup), then update analyze() to reuse that
property while preserving the existing parse error handling.
src/Services/Audits/LaravelConfigAuditService.php (1)

148-167: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Inconsistent tool detection: class_exists vs InstalledVersions::isInstalled.

Telescope is detected via class_exists(), while Debugbar and Clockwork use InstalledVersions::isInstalled(). The $tools array already contains class names that could be used with class_exists for consistency. Consider unifying the detection approach.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Services/Audits/LaravelConfigAuditService.php` around lines 148 - 167,
Unify debug-tool detection in the audit logic by using class availability
consistently: update the Telescope check and the loop over $tools to use
class_exists() with each tool’s class name, rather than mixing class_exists()
and InstalledVersions::isInstalled(). Adjust the foreach destructuring and
related configuration checks while preserving the existing findings.
tests/Commands/WardenSyntaxCommandTest.php (1)

27-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for the audit-error exit path (exit code 2).

WardenSyntaxCommand::handle() returns 2 when $auditResult->errors is non-empty, but no test covers this path. The PR objectives explicitly define exit code 2 for scanner failures, making this a core contract that should be tested.

♻️ Suggested test for the error path
     public function testSyntaxFindingExitsOne(): void
     {
         $finding = new Finding('quality.php.syntax', 'php-syntax', 'Syntax error', Severity::High, 'Parse error', path: 'app/Broken.php');
         $this->mock(PhpSyntaxAuditService::class, function (MockInterface $mock) use ($finding): void {
             $mock->shouldReceive('run')->once()->andReturn(AuditResult::complete('php-syntax', [$finding]));
         });

         $this->artisan('warden:syntax')
             ->expectsOutputToContain('app/Broken.php: Parse error')
             ->assertExitCode(1);
     }
+
+    public function testAuditErrorExitsTwo(): void
+    {
+        $this->mock(PhpSyntaxAuditService::class, function (MockInterface $mock): void {
+            $mock->shouldReceive('run')->once()->andReturn(AuditResult::failed('php-syntax', 'scanner_error', 'PHP binary not found'));
+        });
+
+        $this->artisan('warden:syntax')
+            ->assertExitCode(2);
+    }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Commands/WardenSyntaxCommandTest.php` around lines 27 - 37, Add a test
alongside testSyntaxFindingExitsOne that mocks PhpSyntaxAuditService::run to
return an AuditResult with a non-empty errors collection, invokes the
warden:syntax artisan command, and asserts it exits with code 2. Use the
existing test conventions and relevant AuditResult error structure to cover
WardenSyntaxCommand::handle()’s audit-error path.
src/Commands/WardenBaselineCommand.php (2)

76-85: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use the imported CarbonImmutable instead of the fully qualified name in the instanceof check.

Line 7 already imports Carbon\CarbonImmutable, so line 82 can use CarbonImmutable directly instead of \Carbon\CarbonImmutable.

♻️ Proposed refactor
-        if (!$expiry instanceof \Carbon\CarbonImmutable || $expiry->format('Y-m-d') !== $expires || $expiry->endOfDay()->isPast()) {
+        if (!$expiry instanceof CarbonImmutable || $expiry->format('Y-m-d') !== $expires || $expiry->endOfDay()->isPast()) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Commands/WardenBaselineCommand.php` around lines 76 - 85, In the expiry
validation within the command’s date parsing logic, replace the fully qualified
\Carbon\CarbonImmutable reference in the instanceof check with the already
imported CarbonImmutable class name.

113-118: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider extracting the duplicated csvOption() helper.

The csvOption() method (lines 146–161) is identical to the one in WardenAuditCommand. Extracting it into a shared trait or base command would reduce duplication as both commands evolve.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Commands/WardenBaselineCommand.php` around lines 113 - 118, Extract the
duplicated csvOption() method from WardenBaselineCommand and WardenAuditCommand
into a shared trait or base command, then update both commands to use the shared
implementation while preserving the existing behavior and signature.
src/Commands/WardenSyntaxCommand.php (1)

29-31: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Display audit errors before returning exit code 2.

The command returns 2 when $auditResult->errors is non-empty but never prints those errors, leaving the user with no visible feedback. While PhpSyntaxAuditService currently never produces errors, adding error output future-proofs the command against silent failures.

♻️ Proposed fix
     if ($auditResult->errors !== []) {
+        foreach ($auditResult->errors as $error) {
+            $this->error(sprintf('%s: %s', $error->code, $error->message));
+        }
         return 2;
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Commands/WardenSyntaxCommand.php` around lines 29 - 31, Before returning
exit code 2 in WardenSyntaxCommand, iterate over $auditResult->errors and output
each audit error to the command’s error/output stream, then preserve the
existing return code. Use the surrounding command output conventions and the
PhpSyntaxAuditService result structure to format the messages clearly.
src/Services/Audits/PhpSyntaxAuditService.php (2)

81-91: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Normalise path separators in isExcluded for cross-platform compatibility.

Config exclude values use forward slashes (e.g., bootstrap/cache), but on Windows the relative path uses backslashes. The check str_starts_with($path, rtrim($directory, '/') . DIRECTORY_SEPARATOR) becomes str_starts_with('bootstrap\cache\file.php', 'bootstrap/cache\') on Windows, which is always false. Files in bootstrap/cache would not be excluded on Windows.

♻️ Proposed fix
     /** `@param` list<string> $excluded */
     private function isExcluded(string $path, array $excluded): bool
     {
+        $normalisedPath = str_replace('\\', '/', $path);
         foreach ($excluded as $directory) {
-            if ($path === $directory || str_starts_with($path, rtrim($directory, '/') . DIRECTORY_SEPARATOR)) {
+            $normalisedDirectory = rtrim(str_replace('\\', '/', $directory), '/');
+            if ($normalisedPath === $normalisedDirectory || str_starts_with($normalisedPath, $normalisedDirectory . '/')) {
                 return true;
             }
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Services/Audits/PhpSyntaxAuditService.php` around lines 81 - 91,
Normalize both the input path and each excluded directory to a consistent
separator before comparing them in isExcluded, converting backslashes to forward
slashes and trimming trailing separators. Preserve exact-directory and
descendant matching so values such as bootstrap/cache work on Windows and Unix.

28-29: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Catch ProcessTimedOutException to prevent uncaught audit crashes.

ComposerAuditService catches ProcessTimedOutException and returns AuditResult::failed, but PhpSyntaxAuditService does not. If a php -l process times out, the exception propagates uncaught and crashes the entire audit run. While php -l is fast, the timeout is configurable down to 1 second, and consistency with ComposerAuditService is important for reliability.

🔒️ Proposed fix
 use Symfony\Component\Process\Exception\ProcessTimedOutException;
 use Symfony\Component\Process\Process;

 class PhpSyntaxAuditService implements AuditServiceInterface
 {
     public function getName(): string
     {
         return 'php-syntax';
     }

     public function run(AuditContext $auditContext): AuditResult
     {
         $findings = [];
         foreach ($this->phpFiles() as $path) {
             $process = new Process([PHP_BINARY, '-l', $path], base_path(), null, null, $auditContext->timeout);
-            $process->run();
+            try {
+                $process->run();
+            } catch (ProcessTimedOutException) {
+                return AuditResult::failed($this->getName(), 'timeout', sprintf('PHP syntax lint exceeded the %d second timeout on %s.', $auditContext->timeout, $path));
+            }
             if ($process->isSuccessful()) {
                 continue;
             }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Services/Audits/PhpSyntaxAuditService.php` around lines 28 - 29, Update
PhpSyntaxAuditService to catch ProcessTimedOutException around the Process
execution, matching ComposerAuditService behavior, and return
AuditResult::failed with the appropriate timeout error details instead of
allowing the exception to escape. Use the existing audit context and
result-handling conventions in the service.
src/Services/NotificationDispatcher.php (2)

27-41: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add Finding type hint to the closure parameter.

The $finding parameter on line 28 is untyped. Adding the Finding type hint improves type safety and ensures PHPStan can validate property access.

♻️ Proposed fix
-                $notificationChannel->send(array_map(
-                    static fn ($finding): array => [
+                $notificationChannel->send(array_map(
+                    static fn (Finding $finding): array => [
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Services/NotificationDispatcher.php` around lines 27 - 41, Add the
Finding type hint to the $finding parameter of the static closure inside
NotificationDispatcher’s notification payload mapping, preserving the existing
array mapping logic so PHPStan can validate the accessed properties.

Source: Coding guidelines


50-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Resolve notification channels through the container
NotificationDispatcher is hardcoded to SlackChannel, DiscordChannel, TeamsChannel, and EmailChannel, which blocks custom channel registration. Resolve the channel list from the container instead of instantiating the concrete classes directly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Services/NotificationDispatcher.php` around lines 50 - 54, The channels()
method hardcodes notification channel implementations, preventing custom
registrations. Inject or access the service container in NotificationDispatcher
and resolve all registered NotificationChannel services there, returning the
resolved list while preserving the declared list<NotificationChannel> return
type.
src/Services/AuditRunner.php (2)

22-22: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Make AuditRunner final for consistency.

Other services in this PR (NotificationDispatcher, StorageAuditService, CustomAuditWrapper) are final. Consider the same here unless subclassing is intended.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Services/AuditRunner.php` at line 22, Declare the AuditRunner class as
final, matching NotificationDispatcher, StorageAuditService, and
CustomAuditWrapper unless intentional subclassing requires otherwise.

81-89: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Wrap built-in service construction in try-catch.

Custom audit construction (lines 104–122) is wrapped in try-catch with proper error reporting, but built-in service construction is not. If a built-in service throws during container->make(), the exception propagates unhandled through run() and up to the command, producing a non-deterministic exit code instead of a structured AuditError.

🛡️ Proposed fix
 $services = [
-    $this->container->make(SupplyChainAuditService::class),
-    $this->container->make(ComposerAuditService::class),
-    $this->container->make(NpmAuditService::class),
-    $this->container->make(LaravelConfigAuditService::class),
-    $this->container->make(PlatformAuditService::class),
-    $this->container->make(SourceAuditService::class),
-    $this->container->make(StorageAuditService::class),
 ];
+
+ $builtInClasses = [
+     SupplyChainAuditService::class,
+     ComposerAuditService::class,
+     NpmAuditService::class,
+     LaravelConfigAuditService::class,
+     PlatformAuditService::class,
+     SourceAuditService::class,
+     StorageAuditService::class,
+ ];
+
+ foreach ($builtInClasses as $class) {
+     try {
+         $services[] = $this->container->make($class);
+     } catch (Throwable $throwable) {
+         $errors[] = new AuditError('configuration', 'builtin_audit_initialization_failed', sprintf('%s: %s', $class, $throwable->getMessage()));
+     }
+ }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Services/AuditRunner.php` around lines 81 - 89, Wrap the built-in service
construction in AuditRunner::run() with the same try-catch and error-reporting
behavior used for custom audit construction. Catch exceptions from each
container->make() call (including SupplyChainAuditService, ComposerAuditService,
and the other built-in services), report them through the existing AuditError
mechanism, and ensure run() returns the structured failure result rather than
allowing the exception to propagate.
tests/Services/NotificationDispatcherTest.php (1)

18-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add tests for channel failure and multi-channel dispatch.

The test only covers the happy path with a single configured channel. Consider adding cases for: a channel throwing (verifying warnings are returned), multiple configured channels (verifying assertSentCount increases), and empty findings.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Services/NotificationDispatcherTest.php` around lines 18 - 32, Extend
the NotificationDispatcher tests around
testConfiguredChannelIsDispatchedExactlyOnce with cases for a channel failure
that asserts returned warnings, multiple configured channels that verifies the
expected Http::assertSentCount, and an audit report with empty findings that
validates the dispatcher’s behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/tests.yml:
- Line 26: Configure both actions/checkout@v4 steps with persist-credentials:
false by adding the option under each checkout action in the workflow.
- Around line 10-55: Add a top-level permissions block to the test workflow with
contents: read, restricting GITHUB_TOKEN access to the read-only permission
required by the checkout and validation steps.

In `@readme.md`:
- Around line 270-276: Remove the duplicate second “## License” section in the
README, keeping only the first License heading and its MIT license description.

In `@src/Commands/WardenInitCommand.php`:
- Around line 141-146: Update WardenInitCommand::stub() to detect
file_get_contents failures and throw an exception (or return an explicitly
handled failure) instead of returning an empty string; ensure its callers,
including writeOwnedFile(), propagate or report the error and do not create or
claim creation of an empty workflow file.

In `@src/Reporters/SarifReporter.php`:
- Around line 66-73: In the SARIF location construction within the reporter
method handling `$finding`, do not create a `region` when `$finding->line` is
null; include `region` with `startLine` only when a line number is available,
while always retaining `artifactLocation`.

In `@src/Services/Audits/LaravelConfigAuditService.php`:
- Around line 145-183: The debug-tool findings in toolingFindings() all share
the same ID, causing fingerprint-less suppressions to affect Telescope,
Debugbar, and Clockwork together. Assign distinct stable IDs per tool, including
the Telescope finding and each entry generated from $tools, while preserving
their existing identities and metadata.

In `@src/Services/Audits/PlatformAuditService.php`:
- Around line 114-130: Change composerPlatformPhp() from private to protected so
PlatformAuditServiceTest can override it alongside phpVersion() and
laravelVersion(), ensuring tests use controlled fixture values instead of
reading the real composer.json.

In `@src/Services/Audits/SourceAuditService.php`:
- Around line 47-58: Add a timeout check immediately after the blade analysis in
the audit method, before iterating over PHP files; when timed out, append the
same `AuditError` used in the PHP loop and skip further analysis, while
preserving existing finding and error aggregation behavior.

In `@tests/Services/Audits/LaravelConfigAuditServiceTest.php`:
- Around line 13-21: The CI and secure-production tests rely on the fixture’s
.env not being tracked, making findings environment-dependent. In
LaravelConfigAuditServiceTest, isolate each test with an explicit temporary base
path or stub trackedEnvironmentFindings() before invoking
LaravelConfigAuditService::run, ensuring both profile tests remain independent
of the Testbench fixture’s base path and git state.

---

Nitpick comments:
In `@src/Commands/WardenBaselineCommand.php`:
- Around line 76-85: In the expiry validation within the command’s date parsing
logic, replace the fully qualified \Carbon\CarbonImmutable reference in the
instanceof check with the already imported CarbonImmutable class name.
- Around line 113-118: Extract the duplicated csvOption() method from
WardenBaselineCommand and WardenAuditCommand into a shared trait or base
command, then update both commands to use the shared implementation while
preserving the existing behavior and signature.

In `@src/Commands/WardenSyntaxCommand.php`:
- Around line 29-31: Before returning exit code 2 in WardenSyntaxCommand,
iterate over $auditResult->errors and output each audit error to the command’s
error/output stream, then preserve the existing return code. Use the surrounding
command output conventions and the PhpSyntaxAuditService result structure to
format the messages clearly.

In `@src/Services/AuditRunner.php`:
- Line 22: Declare the AuditRunner class as final, matching
NotificationDispatcher, StorageAuditService, and CustomAuditWrapper unless
intentional subclassing requires otherwise.
- Around line 81-89: Wrap the built-in service construction in
AuditRunner::run() with the same try-catch and error-reporting behavior used for
custom audit construction. Catch exceptions from each container->make() call
(including SupplyChainAuditService, ComposerAuditService, and the other built-in
services), report them through the existing AuditError mechanism, and ensure
run() returns the structured failure result rather than allowing the exception
to propagate.

In `@src/Services/Audits/LaravelConfigAuditService.php`:
- Around line 148-167: Unify debug-tool detection in the audit logic by using
class availability consistently: update the Telescope check and the loop over
$tools to use class_exists() with each tool’s class name, rather than mixing
class_exists() and InstalledVersions::isInstalled(). Adjust the foreach
destructuring and related configuration checks while preserving the existing
findings.

In `@src/Services/Audits/PhpSyntaxAuditService.php`:
- Around line 81-91: Normalize both the input path and each excluded directory
to a consistent separator before comparing them in isExcluded, converting
backslashes to forward slashes and trimming trailing separators. Preserve
exact-directory and descendant matching so values such as bootstrap/cache work
on Windows and Unix.
- Around line 28-29: Update PhpSyntaxAuditService to catch
ProcessTimedOutException around the Process execution, matching
ComposerAuditService behavior, and return AuditResult::failed with the
appropriate timeout error details instead of allowing the exception to escape.
Use the existing audit context and result-handling conventions in the service.

In `@src/Services/NotificationDispatcher.php`:
- Around line 27-41: Add the Finding type hint to the $finding parameter of the
static closure inside NotificationDispatcher’s notification payload mapping,
preserving the existing array mapping logic so PHPStan can validate the accessed
properties.
- Around line 50-54: The channels() method hardcodes notification channel
implementations, preventing custom registrations. Inject or access the service
container in NotificationDispatcher and resolve all registered
NotificationChannel services there, returning the resolved list while preserving
the declared list<NotificationChannel> return type.

In `@src/Services/Source/PhpSourceAnalyzer.php`:
- Around line 26-50: Initialize and retain a single PhpParser parser instance on
the analyzer instead of creating it inside analyze(). Add a parser property and
initialize it once in the constructor (or equivalent setup), then update
analyze() to reuse that property while preserving the existing parse error
handling.

In `@src/ValueObjects/AuditReport.php`:
- Around line 90-122: Cache the results of findings() and errors() in local
variables at the start of jsonSerialize(), then reuse those variables for
counting, status determination, summary fields, and serialized output. Update
the foreach, total/advisory counts, run status, error count, findings, and
errors entries to reference the cached results instead of calling the methods
repeatedly.

In `@tests/Commands/WardenSyntaxCommandTest.php`:
- Around line 27-37: Add a test alongside testSyntaxFindingExitsOne that mocks
PhpSyntaxAuditService::run to return an AuditResult with a non-empty errors
collection, invokes the warden:syntax artisan command, and asserts it exits with
code 2. Use the existing test conventions and relevant AuditResult error
structure to cover WardenSyntaxCommand::handle()’s audit-error path.

In `@tests/Services/NotificationDispatcherTest.php`:
- Around line 18-32: Extend the NotificationDispatcher tests around
testConfiguredChannelIsDispatchedExactlyOnce with cases for a channel failure
that asserts returned warnings, multiple configured channels that verifies the
expected Http::assertSentCount, and an audit report with empty findings that
validates the dispatcher’s behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 16abf9de-fdbc-4d86-b8b2-234e522e6512

📥 Commits

Reviewing files that changed from the base of the PR and between c392c3e and 35abf85.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (83)
  • .github/workflows/tests.yml
  • AGENTS.md
  • UPGRADE.md
  • composer.json
  • contributing.md
  • docs/rules.md
  • phpstan.neon
  • readme.md
  • resources/schemas/warden-report-2.0.0.json
  • src/Commands/WardenAuditCommand.php
  • src/Commands/WardenBaselineCommand.php
  • src/Commands/WardenInitCommand.php
  • src/Commands/WardenScheduleCommand.php
  • src/Commands/WardenSyntaxCommand.php
  • src/Contracts/AuditServiceInterface.php
  • src/Contracts/CustomAudit.php
  • src/Contracts/NotificationChannel.php
  • src/Contracts/ReportFormatter.php
  • src/Enums/RuleDisposition.php
  • src/Enums/Severity.php
  • src/Examples/DatabasePasswordAudit.php
  • src/Notifications/Channels/DiscordChannel.php
  • src/Notifications/Channels/EmailChannel.php
  • src/Notifications/Channels/SlackChannel.php
  • src/Notifications/Channels/TeamsChannel.php
  • src/Notifications/Concerns/HasSeverityHelpers.php
  • src/Providers/WardenServiceProvider.php
  • src/Reporters/ConsoleReporter.php
  • src/Reporters/GitHubReporter.php
  • src/Reporters/GitLabReporter.php
  • src/Reporters/JsonReporter.php
  • src/Reporters/JunitReporter.php
  • src/Reporters/SarifReporter.php
  • src/Services/AuditCacheService.php
  • src/Services/AuditExecutor.php
  • src/Services/AuditRunner.php
  • src/Services/Audits/AbstractAuditService.php
  • src/Services/Audits/ComposerAuditService.php
  • src/Services/Audits/ConfigAuditService.php
  • src/Services/Audits/DebugModeAuditService.php
  • src/Services/Audits/EnvAuditService.php
  • src/Services/Audits/LaravelConfigAuditService.php
  • src/Services/Audits/NpmAuditService.php
  • src/Services/Audits/PhpSyntaxAuditService.php
  • src/Services/Audits/PlatformAuditService.php
  • src/Services/Audits/SourceAuditService.php
  • src/Services/Audits/StorageAuditService.php
  • src/Services/Audits/SupplyChainAuditService.php
  • src/Services/CustomAuditWrapper.php
  • src/Services/NotificationDispatcher.php
  • src/Services/ReportFormatterFactory.php
  • src/Services/RulePolicy.php
  • src/Services/Source/PhpSourceAnalyzer.php
  • src/Services/Source/SourceFileDiscovery.php
  • src/Services/Source/TextSourceAnalyzer.php
  • src/Services/SuppressionService.php
  • src/ValueObjects/AuditContext.php
  • src/ValueObjects/AuditError.php
  • src/ValueObjects/AuditReport.php
  • src/ValueObjects/AuditResult.php
  • src/ValueObjects/Finding.php
  • src/config/warden.php
  • src/database/migrations/2024_01_01_000000_create_warden_audit_history_table.php
  • src/stubs/github-workflow.yml
  • src/stubs/gitlab-ci.yml
  • tests/Commands/WardenAuditCommandTest.php
  • tests/Commands/WardenBaselineCommandTest.php
  • tests/Commands/WardenInitCommandTest.php
  • tests/Commands/WardenSyntaxCommandTest.php
  • tests/Fixtures/competitor-capabilities.php
  • tests/Reporters/ReporterTest.php
  • tests/Services/AuditExecutorTest.php
  • tests/Services/Audits/DebugModeAuditServiceTest.php
  • tests/Services/Audits/DependencyAuditServiceTest.php
  • tests/Services/Audits/LaravelConfigAuditServiceTest.php
  • tests/Services/Audits/PlatformAuditServiceTest.php
  • tests/Services/Audits/SourceAuditServiceTest.php
  • tests/Services/Audits/SupplyChainAuditServiceTest.php
  • tests/Services/CompetitorCapabilityTest.php
  • tests/Services/NotificationDispatcherTest.php
  • tests/Services/SuppressionServiceTest.php
  • tests/TestCase.php
  • tests/ValueObjects/AuditReportTest.php
💤 Files with no reviewable changes (8)
  • src/database/migrations/2024_01_01_000000_create_warden_audit_history_table.php
  • src/Services/Audits/AbstractAuditService.php
  • tests/Services/Audits/DebugModeAuditServiceTest.php
  • src/Commands/WardenScheduleCommand.php
  • src/Services/Audits/DebugModeAuditService.php
  • src/Services/Audits/ConfigAuditService.php
  • src/Services/Audits/EnvAuditService.php
  • src/Services/AuditCacheService.php

Comment thread .github/workflows/tests.yml
Comment thread .github/workflows/tests.yml
Comment thread readme.md Outdated
Comment thread src/Commands/WardenInitCommand.php Outdated
Comment thread src/Reporters/SarifReporter.php
Comment thread src/Services/Audits/LaravelConfigAuditService.php
Comment thread src/Services/Audits/PlatformAuditService.php Outdated
Comment thread src/Services/Audits/SourceAuditService.php
Comment thread tests/Services/Audits/LaravelConfigAuditServiceTest.php
Adds safer audit execution and reporting: separate Telescope, Debugbar, and Clockwork into distinct rule IDs, surface PHP syntax timeouts and command errors, reuse parser/process setup more efficiently, and make SARIF/report output handle missing line/version data cleanly. Also updates init and workflow handling plus related docs/tests.
@dgtlss dgtlss merged commit 19a079f into main Jul 14, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants