diff --git a/.env.example b/.env.example
index bc60417..27e98eb 100644
--- a/.env.example
+++ b/.env.example
@@ -1,9 +1,7 @@
# ==============================================================================
# FILAMENT ACTIONGUARD - ENTERPRISE ENVIRONMENT CONFIGURATION
# ==============================================================================
-# Compliant with Laravel 11.x, 12.x, and Laravel 13.x Enterprise Architecture
-# Includes OWASP Session Hardening, Hyphenated Cache Prefixes,
-# Request Forgery Protection, and First-Party AI SDK Primitives.
+# Local-development example only. Do not copy it to production unchanged.
# ==============================================================================
# ------------------------------------------------------------------------------
@@ -11,7 +9,7 @@
# ------------------------------------------------------------------------------
APP_NAME="Filament ActionGuard"
APP_ENV=local
-APP_KEY=base64:mwI8+tv+nFBfp+UiEtskdA471cijww4UZEwfIW/znbQ=
+APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost:8000
APP_TIMEZONE=UTC
@@ -55,7 +53,7 @@ DB_FOREIGN_KEYS=true
# DB_PASSWORD=your_secure_password
# ------------------------------------------------------------------------------
-# 4. SESSION & COOKIE SECURITY HARDENING (Laravel 13 & OWASP Standards)
+# 4. SESSION & COOKIE SETTINGS
# ------------------------------------------------------------------------------
SESSION_DRIVER=file
SESSION_LIFETIME=120
@@ -64,6 +62,7 @@ SESSION_ENCRYPT=true
SESSION_SERIALIZATION=json
SESSION_PATH=/
SESSION_DOMAIN=null
+# Set true in every HTTPS deployment.
SESSION_SECURE_COOKIE=false
SESSION_HTTP_ONLY=true
SESSION_SAME_SITE=lax
@@ -126,30 +125,23 @@ AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
# ------------------------------------------------------------------------------
-# 11. LARAVEL 13 FIRST-PARTY AI SDK & AGENT ECOSYSTEM
+# 11. ACTIONGUARD POLICY SETTINGS
# ------------------------------------------------------------------------------
-AI_DEFAULT_PROVIDER=openai
-# OPENAI_API_KEY=
-# ANTHROPIC_API_KEY=
-# GEMINI_API_KEY=
-# OLLAMA_BASE_URL=http://localhost:11434
-
-# ------------------------------------------------------------------------------
-# 12. ACTIONGUARD POLICY & ENTERPRISE ENGINE SETTINGS
-# ------------------------------------------------------------------------------
-# Enable or disable ActionGuard evaluation globally
+# Enable or disable ActionGuard evaluation globally. Keep true in production.
ACTIONGUARD_ENABLED=true
# Security posture: Fail-closed (true) blocks actions if a check throws an unhandled exception
ACTIONGUARD_FAIL_CLOSED=true
-# Enterprise Business-Core bridge mode:
-# - false: Standalone Community mode (evaluates native ActionGuard checks)
-# - true: Delegates to allgorithm/business-core operation descriptors when installed
-ACTIONGUARD_ENTERPRISE_MODE=false
+# Disabled by default. Enable only for a controlled, logged maintenance task.
+ACTIONGUARD_ALLOW_BYPASS=false
# Dispatch user-facing Filament danger notifications on state invariant violations
ACTIONGUARD_NOTIFICATIONS_ENABLED=true
-# Enable detailed auditing for invariant checks
+# Enable data-minimised structured audit events; route the channel to your SIEM.
ACTIONGUARD_AUDIT_TRAIL=true
+ACTIONGUARD_AUDIT_CHANNEL=stack
+
+# Relative and HTTPS resolution links are allowed. HTTP is blocked by default.
+ACTIONGUARD_ALLOW_INSECURE_RESOLUTION_URLS=false
diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml
index 1565de2..725a6ea 100644
--- a/.github/workflows/run-tests.yml
+++ b/.github/workflows/run-tests.yml
@@ -59,8 +59,15 @@ jobs:
strategy:
fail-fast: false
matrix:
- php: ['8.3', '8.4', '8.5']
- stability: ['prefer-stable']
+ include:
+ - php: '8.3'
+ stability: 'prefer-stable'
+ - php: '8.4'
+ stability: 'prefer-stable'
+ - php: '8.5'
+ stability: 'prefer-stable'
+ - php: '8.3'
+ stability: 'prefer-lowest'
steps:
- name: Checkout code
@@ -83,3 +90,25 @@ jobs:
- name: Execute tests
run: vendor/bin/pest --ci
+
+ locked-test:
+ name: PHP 8.3 - locked dependencies
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v7
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.3'
+ extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv
+ coverage: none
+
+ - name: Install locked dependencies
+ run: composer install --prefer-dist --no-interaction --ansi
+
+ - name: Execute tests against the release lockfile
+ run: vendor/bin/pest --ci
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6355758..e415322 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -55,6 +55,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Developer Experience & Tooling**
- Root `artisan` CLI bridge to Orchestra Testbench and Workbench environment.
- - Comprehensive test suite with 98 Pest tests and 225 assertions covering architecture, unit checks, traits, enterprise bridge hardening, and demo product scenarios.
+ - Comprehensive test suite with 103 Pest tests and 234 assertions covering architecture, unit checks, traits, enterprise bridge hardening, and demo product scenarios.
[1.0.0]: https://github.com/allgorithm/filament-actionguard/releases/tag/v1.0.0
diff --git a/README.md b/README.md
index f6e48ee..7cc1992 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
-
+
diff --git a/SECURITY.md b/SECURITY.md
index 050522b..3fe1258 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,9 +1,15 @@
# Security Policy
+## Supported Versions
+
+Only the latest released `1.x` version receives security fixes. Security support
+is best effort; do not rely on this package as an authorization boundary.
+
## Reporting Security Vulnerabilities
-If you discover a security vulnerability within **Filament ActionGuard**, please send an e-mail to **security@allgorithm.io** or report it via [GitHub Security Advisories](https://github.com/allgorithm/filament-actionguard/security/advisories/new).
+If you discover a security vulnerability within **Filament ActionGuard**, please send an e-mail to **security-allgorithm@online.de** or report it via [GitHub Security Advisories](https://github.com/allgorithm/filament-actionguard/security/advisories/new).
Please do not disclose security issues publicly in issues or discussions until they have been addressed.
-All security vulnerabilities will be promptly addressed, and we will issue a security advisory and patch as soon as possible.
+We will acknowledge reports within five business days and publish a security
+advisory and patch, or a remediation timeline, once the issue has been triaged.
diff --git a/art/ATTRIBUTION.md b/art/ATTRIBUTION.md
new file mode 100644
index 0000000..c243707
--- /dev/null
+++ b/art/ATTRIBUTION.md
@@ -0,0 +1,8 @@
+# Artwork attribution and AI disclosure
+
+`avatar.png` and `banner.png` were generated with AI for Filament ActionGuard.
+
+They are project artwork, not third-party stock assets, and are distributed with
+this repository under the project MIT license. This disclosure is informational
+and does not assert that the images are protected by copyright in every
+jurisdiction. Do not remove this notice when redistributing the artwork.
diff --git a/composer.json b/composer.json
index 719683f..31b5ad3 100644
--- a/composer.json
+++ b/composer.json
@@ -61,11 +61,14 @@
},
"config": {
"sort-packages": true,
+ "platform": {
+ "php": "8.3.0"
+ },
"allow-plugins": {
"pestphp/pest-plugin": true
}
},
- "minimum-stability": "dev",
+ "minimum-stability": "stable",
"prefer-stable": true,
"suggest": {
"allgorithm/business-core": "Required only for the licensed Enterprise Bridge (^1.2); Community checks work without it."
diff --git a/composer.lock b/composer.lock
index 6f09151..73e838c 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "3274bd8b7b5dadc52ef9c785b4a17656",
+ "content-hash": "797dcf15498488420f2cb9f614fd0829",
"packages": [
{
"name": "anourvalar/eloquent-serialize",
@@ -3250,6 +3250,73 @@
],
"time": "2026-09-07T16:02:43+00:00"
},
+ {
+ "name": "masterminds/html5",
+ "version": "2.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Masterminds/html5-php.git",
+ "reference": "a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7",
+ "reference": "a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6 || ^7 || ^8 || ^9 || ^10"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Masterminds\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Matt Butcher",
+ "email": "technosophos@gmail.com"
+ },
+ {
+ "name": "Matt Farina",
+ "email": "matt@mattfarina.com"
+ },
+ {
+ "name": "Asmir Mustafic",
+ "email": "goetas@gmail.com"
+ }
+ ],
+ "description": "An HTML5 parser and serializer.",
+ "homepage": "http://masterminds.github.io/html5-php",
+ "keywords": [
+ "HTML5",
+ "dom",
+ "html",
+ "parser",
+ "querypath",
+ "serializer",
+ "xml"
+ ],
+ "support": {
+ "issues": "https://github.com/Masterminds/html5-php/issues",
+ "source": "https://github.com/Masterminds/html5-php/tree/2.11.0"
+ },
+ "time": "2026-08-18T06:18:41+00:00"
+ },
{
"name": "monolog/monolog",
"version": "3.12.0",
@@ -5057,21 +5124,22 @@
},
{
"name": "symfony/clock",
- "version": "v8.1.0",
+ "version": "v7.4.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/clock.git",
- "reference": "701ef4de9705d6c32292ebee5e8044094a09fbf6"
+ "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/clock/zipball/701ef4de9705d6c32292ebee5e8044094a09fbf6",
- "reference": "701ef4de9705d6c32292ebee5e8044094a09fbf6",
+ "url": "https://api.github.com/repos/symfony/clock/zipball/674fa3b98e21531dd040e613479f5f6fa8f32111",
+ "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
- "psr/clock": "^1.0"
+ "php": ">=8.2",
+ "psr/clock": "^1.0",
+ "symfony/polyfill-php83": "^1.28"
},
"provide": {
"psr/clock-implementation": "1.0"
@@ -5110,7 +5178,7 @@
"time"
],
"support": {
- "source": "https://github.com/symfony/clock/tree/v8.1.0"
+ "source": "https://github.com/symfony/clock/tree/v7.4.8"
},
"funding": [
{
@@ -5130,53 +5198,51 @@
"type": "tidelift"
}
],
- "time": "2026-05-29T05:06:50+00:00"
+ "time": "2026-03-24T13:12:05+00:00"
},
{
"name": "symfony/console",
- "version": "v8.1.6",
+ "version": "v7.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "eb7d9957d66739649e931ce7a9d05dab69f8abac"
+ "reference": "23d6f88a29f6d0eac45bd77d70307adf83ba7ab0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/eb7d9957d66739649e931ce7a9d05dab69f8abac",
- "reference": "eb7d9957d66739649e931ce7a9d05dab69f8abac",
+ "url": "https://api.github.com/repos/symfony/console/zipball/23d6f88a29f6d0eac45bd77d70307adf83ba7ab0",
+ "reference": "23d6f88a29f6d0eac45bd77d70307adf83ba7ab0",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
+ "php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/polyfill-mbstring": "^1.0",
- "symfony/polyfill-php85": "^1.32",
+ "symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/string": "^7.4.6|^8.0.6"
+ "symfony/string": "^7.2|^8.0"
},
"conflict": {
- "symfony/dependency-injection": "<8.1",
- "symfony/event-dispatcher": "<8.1"
+ "symfony/dependency-injection": "<6.4",
+ "symfony/dotenv": "<6.4",
+ "symfony/event-dispatcher": "<6.4",
+ "symfony/lock": "<6.4",
+ "symfony/process": "<6.4"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^7.4|^8.0",
- "symfony/dependency-injection": "^8.1",
- "symfony/event-dispatcher": "^8.1",
- "symfony/filesystem": "^7.4|^8.0",
- "symfony/http-foundation": "^7.4|^8.0",
- "symfony/http-kernel": "^7.4|^8.0",
- "symfony/lock": "^7.4|^8.0",
- "symfony/messenger": "^7.4|^8.0",
- "symfony/mime": "^7.4|^8.0",
- "symfony/process": "^7.4|^8.0",
- "symfony/stopwatch": "^7.4|^8.0",
- "symfony/uid": "^7.4|^8.0",
- "symfony/validator": "^7.4|^8.0",
- "symfony/var-dumper": "^7.4|^8.0"
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
+ "symfony/http-foundation": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/lock": "^6.4|^7.0|^8.0",
+ "symfony/messenger": "^6.4|^7.0|^8.0",
+ "symfony/process": "^6.4|^7.0|^8.0",
+ "symfony/stopwatch": "^6.4|^7.0|^8.0",
+ "symfony/var-dumper": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -5210,7 +5276,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v8.1.6"
+ "source": "https://github.com/symfony/console/tree/v7.4.18"
},
"funding": [
{
@@ -5230,24 +5296,24 @@
"type": "tidelift"
}
],
- "time": "2026-08-25T14:18:42+00:00"
+ "time": "2026-08-25T14:18:37+00:00"
},
{
"name": "symfony/css-selector",
- "version": "v8.1.6",
+ "version": "v7.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "08e2905152a39cf3fd1745d83f8c483e258887d9"
+ "reference": "fecf40067fc8d8880ea87b8ac227600b9aadd1d0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/08e2905152a39cf3fd1745d83f8c483e258887d9",
- "reference": "08e2905152a39cf3fd1745d83f8c483e258887d9",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/fecf40067fc8d8880ea87b8ac227600b9aadd1d0",
+ "reference": "fecf40067fc8d8880ea87b8ac227600b9aadd1d0",
"shasum": ""
},
"require": {
- "php": ">=8.4.1"
+ "php": ">=8.2"
},
"type": "library",
"autoload": {
@@ -5279,7 +5345,7 @@
"description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/css-selector/tree/v8.1.6"
+ "source": "https://github.com/symfony/css-selector/tree/v7.4.18"
},
"funding": [
{
@@ -5299,7 +5365,7 @@
"type": "tidelift"
}
],
- "time": "2026-08-23T10:06:25+00:00"
+ "time": "2026-08-23T10:03:40+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -5374,32 +5440,33 @@
},
{
"name": "symfony/error-handler",
- "version": "v8.1.5",
+ "version": "v7.4.17",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "8b2a4289ffe5e2dc8fcf645b8e7870e1fa0325ce"
+ "reference": "8373921e231e190a88e2ad526951bbaa791576fa"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/error-handler/zipball/8b2a4289ffe5e2dc8fcf645b8e7870e1fa0325ce",
- "reference": "8b2a4289ffe5e2dc8fcf645b8e7870e1fa0325ce",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/8373921e231e190a88e2ad526951bbaa791576fa",
+ "reference": "8373921e231e190a88e2ad526951bbaa791576fa",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
+ "php": ">=8.2",
"psr/log": "^1|^2|^3",
"symfony/polyfill-php85": "^1.32",
- "symfony/var-dumper": "^7.4|^8.0"
+ "symfony/var-dumper": "^6.4|^7.0|^8.0"
},
"conflict": {
- "symfony/deprecation-contracts": "<2.5"
+ "symfony/deprecation-contracts": "<2.5",
+ "symfony/http-kernel": "<6.4"
},
"require-dev": {
- "symfony/console": "^7.4|^8.0",
+ "symfony/console": "^6.4|^7.0|^8.0",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/http-kernel": "^7.4|^8.0",
- "symfony/serializer": "^7.4|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/serializer": "^6.4|^7.0|^8.0",
"symfony/webpack-encore-bundle": "^1.0|^2.0"
},
"bin": [
@@ -5431,7 +5498,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/error-handler/tree/v8.1.5"
+ "source": "https://github.com/symfony/error-handler/tree/v7.4.17"
},
"funding": [
{
@@ -5451,29 +5518,28 @@
"type": "tidelift"
}
],
- "time": "2026-08-21T17:47:34+00:00"
+ "time": "2026-08-21T17:40:08+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v8.1.5",
+ "version": "v7.4.17",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "7458da64220376b2e0dc2d8451bf43382c1ad297"
+ "reference": "d269974ee93c61d03620ffee358355bfdb471d66"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7458da64220376b2e0dc2d8451bf43382c1ad297",
- "reference": "7458da64220376b2e0dc2d8451bf43382c1ad297",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d269974ee93c61d03620ffee358355bfdb471d66",
+ "reference": "d269974ee93c61d03620ffee358355bfdb471d66",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
- "symfony/deprecation-contracts": "^2.5|^3",
+ "php": ">=8.2",
"symfony/event-dispatcher-contracts": "^2.5|^3"
},
"conflict": {
- "symfony/security-http": "<7.4",
+ "symfony/dependency-injection": "<6.4",
"symfony/service-contracts": "<2.5"
},
"provide": {
@@ -5482,14 +5548,14 @@
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^7.4|^8.0",
- "symfony/dependency-injection": "^7.4|^8.0",
- "symfony/error-handler": "^7.4|^8.0",
- "symfony/expression-language": "^7.4|^8.0",
- "symfony/framework-bundle": "^7.4|^8.0",
- "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/error-handler": "^6.4|^7.0|^8.0",
+ "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/framework-bundle": "^6.4|^7.0|^8.0",
+ "symfony/http-foundation": "^6.4|^7.0|^8.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/stopwatch": "^7.4|^8.0"
+ "symfony/stopwatch": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -5517,7 +5583,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/event-dispatcher/tree/v8.1.5"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.17"
},
"funding": [
{
@@ -5537,7 +5603,7 @@
"type": "tidelift"
}
],
- "time": "2026-08-21T17:47:34+00:00"
+ "time": "2026-08-21T17:40:08+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@@ -5621,23 +5687,23 @@
},
{
"name": "symfony/finder",
- "version": "v8.1.5",
+ "version": "v7.4.17",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "8d7acede2b2ae07605783d1c43e49b5767036474"
+ "reference": "5ce28827081f6d1f0c32eaf3882750f19cb5bbe6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/8d7acede2b2ae07605783d1c43e49b5767036474",
- "reference": "8d7acede2b2ae07605783d1c43e49b5767036474",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/5ce28827081f6d1f0c32eaf3882750f19cb5bbe6",
+ "reference": "5ce28827081f6d1f0c32eaf3882750f19cb5bbe6",
"shasum": ""
},
"require": {
- "php": ">=8.4.1"
+ "php": ">=8.2"
},
"require-dev": {
- "symfony/filesystem": "^7.4|^8.0"
+ "symfony/filesystem": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -5665,7 +5731,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v8.1.5"
+ "source": "https://github.com/symfony/finder/tree/v7.4.17"
},
"funding": [
{
@@ -5685,26 +5751,28 @@
"type": "tidelift"
}
],
- "time": "2026-08-21T12:16:08+00:00"
+ "time": "2026-08-21T12:09:28+00:00"
},
{
"name": "symfony/html-sanitizer",
- "version": "v8.1.6",
+ "version": "v7.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/html-sanitizer.git",
- "reference": "f8bbdb0704e6b6e9a3412481c1a87886a0633199"
+ "reference": "5394e10c12b6190c019e3112e8b534180c22f0da"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/f8bbdb0704e6b6e9a3412481c1a87886a0633199",
- "reference": "f8bbdb0704e6b6e9a3412481c1a87886a0633199",
+ "url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/5394e10c12b6190c019e3112e8b534180c22f0da",
+ "reference": "5394e10c12b6190c019e3112e8b534180c22f0da",
"shasum": ""
},
"require": {
"ext-dom": "*",
"league/uri": "^6.5|^7.0",
- "php": ">=8.4.1"
+ "masterminds/html5": "^2.7.2",
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3"
},
"type": "library",
"autoload": {
@@ -5737,7 +5805,7 @@
"sanitizer"
],
"support": {
- "source": "https://github.com/symfony/html-sanitizer/tree/v8.1.6"
+ "source": "https://github.com/symfony/html-sanitizer/tree/v7.4.18"
},
"funding": [
{
@@ -5757,40 +5825,41 @@
"type": "tidelift"
}
],
- "time": "2026-08-30T01:03:44+00:00"
+ "time": "2026-08-30T00:47:26+00:00"
},
{
"name": "symfony/http-foundation",
- "version": "v8.1.6",
+ "version": "v7.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "093b78326f649c3a9db922b9f17123b6aeb3b8fb"
+ "reference": "d070b716a32fbe3bf04204db0f58ace73b86d133"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/093b78326f649c3a9db922b9f17123b6aeb3b8fb",
- "reference": "093b78326f649c3a9db922b9f17123b6aeb3b8fb",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d070b716a32fbe3bf04204db0f58ace73b86d133",
+ "reference": "d070b716a32fbe3bf04204db0f58ace73b86d133",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
+ "php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "^1.1"
},
"conflict": {
- "doctrine/dbal": "<4.3"
+ "doctrine/dbal": "<3.6",
+ "symfony/cache": "<6.4.12|>=7.0,<7.1.5"
},
"require-dev": {
- "doctrine/dbal": "^4.3",
+ "doctrine/dbal": "^3.6|^4",
"predis/predis": "^1.1|^2.0",
- "symfony/cache": "^7.4|^8.0",
- "symfony/clock": "^7.4|^8.0",
- "symfony/dependency-injection": "^7.4|^8.0",
- "symfony/expression-language": "^7.4|^8.0",
- "symfony/http-kernel": "^7.4|^8.0",
- "symfony/mime": "^7.4|^8.0",
- "symfony/rate-limiter": "^7.4|^8.0"
+ "symfony/cache": "^6.4.12|^7.1.5|^8.0",
+ "symfony/clock": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/mime": "^6.4|^7.0|^8.0",
+ "symfony/rate-limiter": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -5818,7 +5887,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-foundation/tree/v8.1.6"
+ "source": "https://github.com/symfony/http-foundation/tree/v7.4.18"
},
"funding": [
{
@@ -5838,69 +5907,78 @@
"type": "tidelift"
}
],
- "time": "2026-08-30T20:10:55+00:00"
+ "time": "2026-08-30T20:10:52+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v8.1.6",
+ "version": "v7.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "2f73beb7c6f1a97d2c17bbf4dbd59da8cc18b355"
+ "reference": "275d2d2d24530f2a0eaf17704a3a93860a036351"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2f73beb7c6f1a97d2c17bbf4dbd59da8cc18b355",
- "reference": "2f73beb7c6f1a97d2c17bbf4dbd59da8cc18b355",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/275d2d2d24530f2a0eaf17704a3a93860a036351",
+ "reference": "275d2d2d24530f2a0eaf17704a3a93860a036351",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
+ "php": ">=8.2",
"psr/log": "^1|^2|^3",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/error-handler": "^7.4|^8.0",
- "symfony/event-dispatcher": "^7.4|^8.0",
+ "symfony/error-handler": "^6.4|^7.0|^8.0",
+ "symfony/event-dispatcher": "^7.3|^8.0",
"symfony/http-foundation": "^7.4|^8.0",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
- "symfony/dependency-injection": "<8.1",
+ "symfony/browser-kit": "<6.4",
+ "symfony/cache": "<6.4",
+ "symfony/config": "<6.4",
+ "symfony/console": "<6.4",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/doctrine-bridge": "<6.4",
"symfony/flex": "<2.10",
+ "symfony/form": "<6.4",
+ "symfony/http-client": "<6.4",
"symfony/http-client-contracts": "<2.5",
- "symfony/serializer": "<7.4.15|>=8.0,<8.0.15|>=8.1,<8.1.2",
+ "symfony/mailer": "<6.4",
+ "symfony/messenger": "<6.4",
+ "symfony/translation": "<6.4",
"symfony/translation-contracts": "<2.5",
- "symfony/var-dumper": "<8.1",
- "symfony/web-profiler-bundle": "<8.1",
- "twig/twig": "<3.21"
+ "symfony/twig-bridge": "<6.4",
+ "symfony/validator": "<6.4",
+ "symfony/var-dumper": "<6.4",
+ "twig/twig": "<3.12"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/cache": "^1.0|^2.0|^3.0",
- "symfony/browser-kit": "^7.4|^8.0",
- "symfony/clock": "^7.4|^8.0",
- "symfony/config": "^7.4|^8.0",
- "symfony/console": "^7.4|^8.0",
- "symfony/css-selector": "^7.4|^8.0",
- "symfony/dependency-injection": "^8.1",
- "symfony/dom-crawler": "^7.4|^8.0",
- "symfony/expression-language": "^7.4|^8.0",
- "symfony/finder": "^7.4|^8.0",
+ "symfony/browser-kit": "^6.4|^7.0|^8.0",
+ "symfony/clock": "^6.4|^7.0|^8.0",
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/console": "^6.4|^7.0|^8.0",
+ "symfony/css-selector": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4.1|^7.0.1|^8.0",
+ "symfony/dom-crawler": "^6.4|^7.0|^8.0",
+ "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/finder": "^6.4|^7.0|^8.0",
"symfony/http-client-contracts": "^2.5|^3",
- "symfony/process": "^7.4|^8.0",
- "symfony/property-access": "^7.4|^8.0",
- "symfony/rate-limiter": "^7.4|^8.0",
- "symfony/routing": "^7.4|^8.0",
- "symfony/serializer": "^7.4|^8.0",
- "symfony/stopwatch": "^7.4|^8.0",
- "symfony/translation": "^7.4|^8.0",
+ "symfony/process": "^6.4|^7.0|^8.0",
+ "symfony/property-access": "^7.1|^8.0",
+ "symfony/routing": "^6.4|^7.0|^8.0",
+ "symfony/serializer": "^7.1|^8.0",
+ "symfony/stopwatch": "^6.4|^7.0|^8.0",
+ "symfony/translation": "^6.4|^7.0|^8.0",
"symfony/translation-contracts": "^2.5|^3",
- "symfony/uid": "^7.4|^8.0",
- "symfony/validator": "^7.4|^8.0",
- "symfony/var-dumper": "^8.1",
- "symfony/var-exporter": "^7.4|^8.0",
- "twig/twig": "^3.21|^4.0"
+ "symfony/uid": "^6.4|^7.0|^8.0",
+ "symfony/validator": "^6.4|^7.0|^8.0",
+ "symfony/var-dumper": "^6.4|^7.0|^8.0",
+ "symfony/var-exporter": "^6.4|^7.0|^8.0",
+ "twig/twig": "^3.12|^4.0"
},
"type": "library",
"autoload": {
@@ -5928,7 +6006,7 @@
"description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-kernel/tree/v8.1.6"
+ "source": "https://github.com/symfony/http-kernel/tree/v7.4.18"
},
"funding": [
{
@@ -5948,39 +6026,43 @@
"type": "tidelift"
}
],
- "time": "2026-08-30T21:40:49+00:00"
+ "time": "2026-08-30T21:24:29+00:00"
},
{
"name": "symfony/mailer",
- "version": "v8.1.5",
+ "version": "v7.4.17",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
- "reference": "89f43137da74b8f1aab37c99926482b7084f51b9"
+ "reference": "b17c9bf3a551d5f635638a3b6c05f06c4dc87584"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mailer/zipball/89f43137da74b8f1aab37c99926482b7084f51b9",
- "reference": "89f43137da74b8f1aab37c99926482b7084f51b9",
+ "url": "https://api.github.com/repos/symfony/mailer/zipball/b17c9bf3a551d5f635638a3b6c05f06c4dc87584",
+ "reference": "b17c9bf3a551d5f635638a3b6c05f06c4dc87584",
"shasum": ""
},
"require": {
"egulias/email-validator": "^2.1.10|^3|^4",
- "php": ">=8.4.1",
+ "php": ">=8.2",
"psr/event-dispatcher": "^1",
"psr/log": "^1|^2|^3",
- "symfony/event-dispatcher": "^7.4|^8.0",
- "symfony/mime": "^7.4|^8.0",
+ "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
+ "symfony/mime": "^7.2|^8.0",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
- "symfony/http-client-contracts": "<2.5"
+ "symfony/http-client-contracts": "<2.5",
+ "symfony/http-kernel": "<6.4",
+ "symfony/messenger": "<6.4",
+ "symfony/mime": "<6.4",
+ "symfony/twig-bridge": "<6.4"
},
"require-dev": {
- "symfony/console": "^7.4|^8.0",
- "symfony/http-client": "^7.4|^8.0",
- "symfony/messenger": "^7.4|^8.0",
- "symfony/twig-bridge": "^7.4|^8.0"
+ "symfony/console": "^6.4|^7.0|^8.0",
+ "symfony/http-client": "^6.4|^7.0|^8.0",
+ "symfony/messenger": "^6.4|^7.0|^8.0",
+ "symfony/twig-bridge": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -6008,7 +6090,7 @@
"description": "Helps sending emails",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/mailer/tree/v8.1.5"
+ "source": "https://github.com/symfony/mailer/tree/v7.4.17"
},
"funding": [
{
@@ -6028,41 +6110,44 @@
"type": "tidelift"
}
],
- "time": "2026-08-21T17:47:34+00:00"
+ "time": "2026-08-21T17:40:08+00:00"
},
{
"name": "symfony/mime",
- "version": "v8.1.6",
+ "version": "v7.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "1b36ccfd7ccb9ad1d6eafb9024b3dd3d9606b15f"
+ "reference": "bf328d82105831db3e409195db0540ff57f27c80"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/1b36ccfd7ccb9ad1d6eafb9024b3dd3d9606b15f",
- "reference": "1b36ccfd7ccb9ad1d6eafb9024b3dd3d9606b15f",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/bf328d82105831db3e409195db0540ff57f27c80",
+ "reference": "bf328d82105831db3e409195db0540ff57f27c80",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "^1.0"
},
"conflict": {
"egulias/email-validator": "~3.0.0",
"phpdocumentor/reflection-docblock": "<5.2|>=7",
- "phpdocumentor/type-resolver": "<1.5.1"
+ "phpdocumentor/type-resolver": "<1.5.1",
+ "symfony/mailer": "<6.4",
+ "symfony/serializer": "<6.4.3|>7.0,<7.0.3"
},
"require-dev": {
"egulias/email-validator": "^2.1.10|^3.1|^4",
"league/html-to-markdown": "^5.0",
"phpdocumentor/reflection-docblock": "^5.2|^6.0",
- "symfony/dependency-injection": "^7.4|^8.0",
- "symfony/process": "^7.4|^8.0",
- "symfony/property-access": "^7.4|^8.0",
- "symfony/property-info": "^7.4|^8.0",
- "symfony/serializer": "^7.4.17|^8.1.5"
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/process": "^6.4|^7.0|^8.0",
+ "symfony/property-access": "^6.4|^7.0|^8.0",
+ "symfony/property-info": "^6.4|^7.0|^8.0",
+ "symfony/serializer": "^6.4.44|^7.4.17|^8.1.5"
},
"type": "library",
"autoload": {
@@ -6094,7 +6179,7 @@
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v8.1.6"
+ "source": "https://github.com/symfony/mime/tree/v7.4.18"
},
"funding": [
{
@@ -6114,7 +6199,7 @@
"type": "tidelift"
}
],
- "time": "2026-08-22T09:06:25+00:00"
+ "time": "2026-08-22T09:04:42+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -6702,6 +6787,86 @@
],
"time": "2026-05-26T12:45:58+00:00"
},
+ {
+ "name": "symfony/polyfill-php83",
+ "version": "v1.41.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php83.git",
+ "reference": "5ea99087fb99c273a9b9236ed4c31e78b16103c6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/5ea99087fb99c273a9b9236ed4c31e78b16103c6",
+ "reference": "5ea99087fb99c273a9b9236ed4c31e78b16103c6",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php83\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php83/tree/v1.41.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-01T12:47:55+00:00"
+ },
{
"name": "symfony/polyfill-php84",
"version": "v1.38.1",
@@ -7027,20 +7192,20 @@
},
{
"name": "symfony/process",
- "version": "v8.1.6",
+ "version": "v7.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "d863f5e70d7c87abb906ac11b61f83036093000b"
+ "reference": "058d17fc284cce14efb2385783b55014a461b176"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/d863f5e70d7c87abb906ac11b61f83036093000b",
- "reference": "d863f5e70d7c87abb906ac11b61f83036093000b",
+ "url": "https://api.github.com/repos/symfony/process/zipball/058d17fc284cce14efb2385783b55014a461b176",
+ "reference": "058d17fc284cce14efb2385783b55014a461b176",
"shasum": ""
},
"require": {
- "php": ">=8.4.1"
+ "php": ">=8.2"
},
"type": "library",
"autoload": {
@@ -7068,7 +7233,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v8.1.6"
+ "source": "https://github.com/symfony/process/tree/v7.4.18"
},
"funding": [
{
@@ -7088,33 +7253,38 @@
"type": "tidelift"
}
],
- "time": "2026-08-21T17:47:34+00:00"
+ "time": "2026-08-21T17:40:08+00:00"
},
{
"name": "symfony/routing",
- "version": "v8.1.6",
+ "version": "v7.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "3c188091b6b4fa2e4bc83a135caede12deb8576c"
+ "reference": "ddd558991e98f693ae6bf5063cc1b0362c6bbec3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/3c188091b6b4fa2e4bc83a135caede12deb8576c",
- "reference": "3c188091b6b4fa2e4bc83a135caede12deb8576c",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/ddd558991e98f693ae6bf5063cc1b0362c6bbec3",
+ "reference": "ddd558991e98f693ae6bf5063cc1b0362c6bbec3",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
+ "php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3"
},
+ "conflict": {
+ "symfony/config": "<6.4",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/yaml": "<6.4"
+ },
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^7.4|^8.0",
- "symfony/dependency-injection": "^7.4|^8.0",
- "symfony/expression-language": "^7.4|^8.0",
- "symfony/http-foundation": "^7.4|^8.0",
- "symfony/yaml": "^7.4|^8.0"
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/http-foundation": "^6.4|^7.0|^8.0",
+ "symfony/yaml": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -7148,7 +7318,7 @@
"url"
],
"support": {
- "source": "https://github.com/symfony/routing/tree/v8.1.6"
+ "source": "https://github.com/symfony/routing/tree/v7.4.18"
},
"funding": [
{
@@ -7168,7 +7338,7 @@
"type": "tidelift"
}
],
- "time": "2026-08-17T13:18:34+00:00"
+ "time": "2026-08-17T13:12:36+00:00"
},
{
"name": "symfony/service-contracts",
@@ -7259,34 +7429,35 @@
},
{
"name": "symfony/string",
- "version": "v8.1.2",
+ "version": "v7.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc"
+ "reference": "e394af32256bf9e7bf80849d95e589167c10097b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc",
- "reference": "286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc",
+ "url": "https://api.github.com/repos/symfony/string/zipball/e394af32256bf9e7bf80849d95e589167c10097b",
+ "reference": "e394af32256bf9e7bf80849d95e589167c10097b",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
- "symfony/polyfill-ctype": "^1.8",
- "symfony/polyfill-intl-grapheme": "^1.33",
- "symfony/polyfill-intl-normalizer": "^1.0",
- "symfony/polyfill-mbstring": "^1.0"
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3.0",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-intl-grapheme": "~1.33",
+ "symfony/polyfill-intl-normalizer": "~1.0",
+ "symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
- "symfony/emoji": "^7.4|^8.0",
- "symfony/http-client": "^7.4|^8.0",
- "symfony/intl": "^7.4|^8.0",
+ "symfony/emoji": "^7.1|^8.0",
+ "symfony/http-client": "^6.4|^7.0|^8.0",
+ "symfony/intl": "^6.4|^7.0|^8.0",
"symfony/translation-contracts": "^2.5|^3.0",
- "symfony/var-exporter": "^7.4|^8.0"
+ "symfony/var-exporter": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -7325,7 +7496,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v8.1.2"
+ "source": "https://github.com/symfony/string/tree/v7.4.15"
},
"funding": [
{
@@ -7345,31 +7516,38 @@
"type": "tidelift"
}
],
- "time": "2026-07-28T07:35:25+00:00"
+ "time": "2026-07-28T07:33:02+00:00"
},
{
"name": "symfony/translation",
- "version": "v8.1.5",
+ "version": "v7.4.17",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "d9e1caba0d6b6f9a26710af8a2f88d37f001215a"
+ "reference": "2ee1e4a3b32a528a642babe041ff7c440b213b4b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/d9e1caba0d6b6f9a26710af8a2f88d37f001215a",
- "reference": "d9e1caba0d6b6f9a26710af8a2f88d37f001215a",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/2ee1e4a3b32a528a642babe041ff7c440b213b4b",
+ "reference": "2ee1e4a3b32a528a642babe041ff7c440b213b4b",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
- "symfony/polyfill-mbstring": "^1.0",
- "symfony/translation-contracts": "^3.6.1"
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/translation-contracts": "^2.5.3|^3.3"
},
"conflict": {
"nikic/php-parser": "<5.0",
+ "symfony/config": "<6.4",
+ "symfony/console": "<6.4",
+ "symfony/dependency-injection": "<6.4",
"symfony/http-client-contracts": "<2.5",
- "symfony/service-contracts": "<2.5"
+ "symfony/http-kernel": "<6.4",
+ "symfony/service-contracts": "<2.5",
+ "symfony/twig-bundle": "<6.4",
+ "symfony/yaml": "<6.4"
},
"provide": {
"symfony/translation-implementation": "2.3|3.0"
@@ -7377,17 +7555,17 @@
"require-dev": {
"nikic/php-parser": "^5.0",
"psr/log": "^1|^2|^3",
- "symfony/config": "^7.4|^8.0",
- "symfony/console": "^7.4|^8.0",
- "symfony/dependency-injection": "^7.4|^8.0",
- "symfony/finder": "^7.4|^8.0",
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/console": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/finder": "^6.4|^7.0|^8.0",
"symfony/http-client-contracts": "^2.5|^3.0",
- "symfony/http-kernel": "^7.4|^8.0",
- "symfony/intl": "^7.4|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/intl": "^6.4|^7.0|^8.0",
"symfony/polyfill-intl-icu": "^1.21",
- "symfony/routing": "^7.4|^8.0",
+ "symfony/routing": "^6.4|^7.0|^8.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/yaml": "^7.4|^8.0"
+ "symfony/yaml": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -7418,7 +7596,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/translation/tree/v8.1.5"
+ "source": "https://github.com/symfony/translation/tree/v7.4.17"
},
"funding": [
{
@@ -7438,7 +7616,7 @@
"type": "tidelift"
}
],
- "time": "2026-08-21T17:47:34+00:00"
+ "time": "2026-08-21T17:40:08+00:00"
},
{
"name": "symfony/translation-contracts",
@@ -7524,24 +7702,24 @@
},
{
"name": "symfony/uid",
- "version": "v8.1.5",
+ "version": "v7.4.17",
"source": {
"type": "git",
"url": "https://github.com/symfony/uid.git",
- "reference": "a08aef47989093f32fe50fd11859be1b427df389"
+ "reference": "69d732355a139c6f8881337d28515aa01f12b8be"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/uid/zipball/a08aef47989093f32fe50fd11859be1b427df389",
- "reference": "a08aef47989093f32fe50fd11859be1b427df389",
+ "url": "https://api.github.com/repos/symfony/uid/zipball/69d732355a139c6f8881337d28515aa01f12b8be",
+ "reference": "69d732355a139c6f8881337d28515aa01f12b8be",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
+ "php": ">=8.2",
"symfony/polyfill-uuid": "^1.15"
},
"require-dev": {
- "symfony/console": "^7.4|^8.0"
+ "symfony/console": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -7578,7 +7756,7 @@
"uuid"
],
"support": {
- "source": "https://github.com/symfony/uid/tree/v8.1.5"
+ "source": "https://github.com/symfony/uid/tree/v7.4.17"
},
"funding": [
{
@@ -7598,35 +7776,35 @@
"type": "tidelift"
}
],
- "time": "2026-08-11T13:39:01+00:00"
+ "time": "2026-08-11T07:38:58+00:00"
},
{
"name": "symfony/var-dumper",
- "version": "v8.1.6",
+ "version": "v7.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "3783365b58972f4779254d98372af80fbf15e170"
+ "reference": "e088da50b813f32473a76871616cbb8fa54653a8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3783365b58972f4779254d98372af80fbf15e170",
- "reference": "3783365b58972f4779254d98372af80fbf15e170",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e088da50b813f32473a76871616cbb8fa54653a8",
+ "reference": "e088da50b813f32473a76871616cbb8fa54653a8",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
- "symfony/polyfill-mbstring": "^1.0"
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
- "symfony/console": "<7.4",
- "symfony/error-handler": "<7.4"
+ "symfony/console": "<6.4"
},
"require-dev": {
- "symfony/console": "^7.4|^8.0",
- "symfony/http-kernel": "^7.4|^8.0",
- "symfony/process": "^7.4|^8.0",
- "symfony/uid": "^7.4|^8.0",
+ "symfony/console": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/process": "^6.4|^7.0|^8.0",
+ "symfony/uid": "^6.4|^7.0|^8.0",
"twig/twig": "^3.12|^4.0"
},
"bin": [
@@ -7665,7 +7843,7 @@
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v8.1.6"
+ "source": "https://github.com/symfony/var-dumper/tree/v7.4.18"
},
"funding": [
{
@@ -7685,7 +7863,7 @@
"type": "tidelift"
}
],
- "time": "2026-08-30T20:10:55+00:00"
+ "time": "2026-08-30T20:10:52+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
@@ -12052,110 +12230,30 @@
],
"time": "2024-10-20T05:08:20+00:00"
},
- {
- "name": "symfony/polyfill-php83",
- "version": "v1.41.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-php83.git",
- "reference": "5ea99087fb99c273a9b9236ed4c31e78b16103c6"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/5ea99087fb99c273a9b9236ed4c31e78b16103c6",
- "reference": "5ea99087fb99c273a9b9236ed4c31e78b16103c6",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2"
- },
- "type": "library",
- "extra": {
- "thanks": {
- "url": "https://github.com/symfony/polyfill",
- "name": "symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Php83\\": ""
- },
- "classmap": [
- "Resources/stubs"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "polyfill",
- "portable",
- "shim"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-php83/tree/v1.41.0"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://github.com/nicolas-grekas",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "time": "2026-07-01T12:47:55+00:00"
- },
{
"name": "symfony/yaml",
- "version": "v8.1.6",
+ "version": "v7.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "0b4aa53a67f9fece88c665f1a1dadcfd25d93fe5"
+ "reference": "4cef939e55b8a21c5780418de0d98ab00d0736e1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/0b4aa53a67f9fece88c665f1a1dadcfd25d93fe5",
- "reference": "0b4aa53a67f9fece88c665f1a1dadcfd25d93fe5",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/4cef939e55b8a21c5780418de0d98ab00d0736e1",
+ "reference": "4cef939e55b8a21c5780418de0d98ab00d0736e1",
"shasum": ""
},
"require": {
- "php": ">=8.4.1",
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
- "symfony/console": "<7.4"
+ "symfony/console": "<6.4"
},
"require-dev": {
- "symfony/console": "^7.4|^8.0",
- "yaml/yaml-test-suite": "*"
+ "symfony/console": "^6.4|^7.0|^8.0"
},
"bin": [
"Resources/bin/yaml-lint"
@@ -12186,7 +12284,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/yaml/tree/v8.1.6"
+ "source": "https://github.com/symfony/yaml/tree/v7.4.18"
},
"funding": [
{
@@ -12206,7 +12304,7 @@
"type": "tidelift"
}
],
- "time": "2026-08-30T01:03:44+00:00"
+ "time": "2026-08-30T00:47:26+00:00"
},
{
"name": "ta-tikoma/phpunit-architecture-test",
@@ -12385,7 +12483,7 @@
}
],
"aliases": [],
- "minimum-stability": "dev",
+ "minimum-stability": "stable",
"stability-flags": {},
"prefer-stable": true,
"prefer-lowest": false,
@@ -12393,5 +12491,8 @@
"php": "^8.3|^8.4|^8.5"
},
"platform-dev": {},
+ "platform-overrides": {
+ "php": "8.3.0"
+ },
"plugin-api-version": "2.9.0"
}
diff --git a/config/filament-actionguard.php b/config/filament-actionguard.php
new file mode 100644
index 0000000..26541fa
--- /dev/null
+++ b/config/filament-actionguard.php
@@ -0,0 +1,31 @@
+ (bool) env('ACTIONGUARD_ENABLED', true),
+
+ /* Errors in a check must block the operation unless explicitly disabled. */
+ 'fail_closed' => (bool) env('ACTIONGUARD_FAIL_CLOSED', true),
+
+ /* A bypass is disabled by default and is always scoped to one callback. */
+ 'allow_bypass' => (bool) env('ACTIONGUARD_ALLOW_BYPASS', false),
+
+ 'notifications' => (bool) env('ACTIONGUARD_NOTIFICATIONS_ENABLED', true),
+
+ /*
+ * The package never logs model attributes, messages, record IDs, or actor IDs.
+ * Applications may route this channel to their central audit system.
+ */
+ 'audit' => [
+ 'enabled' => (bool) env('ACTIONGUARD_AUDIT_TRAIL', false),
+ 'channel' => env('ACTIONGUARD_AUDIT_CHANNEL'),
+ ],
+
+ /* Relative URLs and HTTPS are allowed; HTTP requires an explicit opt-in. */
+ 'allow_insecure_resolution_urls' => (bool) env('ACTIONGUARD_ALLOW_INSECURE_RESOLUTION_URLS', false),
+];
diff --git a/src/ActionGuardServiceProvider.php b/src/ActionGuardServiceProvider.php
index 582c152..9742e23 100644
--- a/src/ActionGuardServiceProvider.php
+++ b/src/ActionGuardServiceProvider.php
@@ -26,6 +26,7 @@ public function configurePackage(Package $package): void
*/
$package
->name('filament-actionguard')
+ ->hasConfigFile()
->hasTranslations()
->hasViews();
}
diff --git a/src/Actions/ActionGuardAction.php b/src/Actions/ActionGuardAction.php
index bdf905d..73686dd 100644
--- a/src/Actions/ActionGuardAction.php
+++ b/src/Actions/ActionGuardAction.php
@@ -6,12 +6,14 @@
use Allgorithm\FilamentActionGuard\Contracts\ActionGuardCheckContract;
use Allgorithm\FilamentActionGuard\Results\ActionGuardResult;
use Allgorithm\FilamentActionGuard\Results\CheckResult;
+use Allgorithm\FilamentActionGuard\Support\ActionGuardAudit;
use Filament\Actions\Action;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\HtmlString;
use Illuminate\Support\Str;
+use InvalidArgumentException;
class ActionGuardAction extends Action
{
@@ -30,7 +32,7 @@ protected function setUp(): void
$this->modalWidth('lg');
$rawLabel = $this->getLabel();
- $label = $rawLabel instanceof Htmlable ? $rawLabel->toHtml() : (string) ($rawLabel ?? '');
+ $label = $rawLabel instanceof Htmlable ? strip_tags($rawLabel->toHtml()) : (string) ($rawLabel ?? '');
$this->modalHeading(__('filament-actionguard::ui.modal.heading', ['label' => $label]));
$this->modalContent(function (ActionGuardAction $action, ?Model $record) {
return $action->evaluateAndRender($record);
@@ -62,7 +64,11 @@ public function checks(array $checks): static
{
$this->checks = array_map(function ($check) {
if (is_string($check) && class_exists($check)) {
- return app($check);
+ $check = app($check);
+ }
+
+ if (! $check instanceof ActionGuardCheckContract) {
+ throw new InvalidArgumentException('Every ActionGuard check must implement '.ActionGuardCheckContract::class.'.');
}
return $check;
@@ -104,6 +110,10 @@ public function forState(string $state): static
public function evaluateChecks(?Model $record): ActionGuardResult
{
+ if (! config('filament-actionguard.enabled', true)) {
+ return ActionGuardResult::fromChecks([]);
+ }
+
$checks = $this->checks;
// Auto-resolve guards from model if none were explicitly set and model uses HasActionGuards
@@ -120,7 +130,7 @@ public function evaluateChecks(?Model $record): ActionGuardResult
label: __('filament-actionguard::ui.errors.record_label'),
message: __('filament-actionguard::ui.errors.record_missing'),
),
- ]);
+ ], (bool) config('filament-actionguard.fail_closed', true));
}
return ActionGuardResult::fromChecks([]);
@@ -142,7 +152,15 @@ public function evaluateChecks(?Model $record): ActionGuardResult
}
}
- return ActionGuardResult::fromChecks($results);
+ $result = ActionGuardResult::fromChecks($results, (bool) config('filament-actionguard.fail_closed', true));
+
+ ActionGuardAudit::record('action_evaluated', [
+ 'passed' => $result->passed,
+ 'failed' => $result->summary['failed'],
+ 'errors' => $result->summary['errors'],
+ ]);
+
+ return $result;
}
public function evaluateAndRender(?Model $record): HtmlString|View|string
diff --git a/src/Bridge/BusinessCoreGuardAdapter.php b/src/Bridge/BusinessCoreGuardAdapter.php
index f5bf157..98f12e6 100644
--- a/src/Bridge/BusinessCoreGuardAdapter.php
+++ b/src/Bridge/BusinessCoreGuardAdapter.php
@@ -155,6 +155,11 @@ protected function sanitizeResolutionUrl(mixed $url): ?string
$scheme = parse_url($url, PHP_URL_SCHEME);
- return in_array(strtolower((string) $scheme), ['https', 'http'], true) ? $url : null;
+ $allowedSchemes = ['https'];
+ if (config('filament-actionguard.allow_insecure_resolution_urls', false)) {
+ $allowedSchemes[] = 'http';
+ }
+
+ return in_array(strtolower((string) $scheme), $allowedSchemes, true) ? $url : null;
}
}
diff --git a/src/Checks/CallbackCheck.php b/src/Checks/CallbackCheck.php
index 7515e14..e014849 100644
--- a/src/Checks/CallbackCheck.php
+++ b/src/Checks/CallbackCheck.php
@@ -6,6 +6,7 @@
use Allgorithm\FilamentActionGuard\Results\CheckResult;
use Closure;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Str;
class CallbackCheck implements ActionGuardCheckContract
{
@@ -57,10 +58,13 @@ public function evaluate(Model $record): CheckResult
return $result;
} catch (\Throwable $e) {
+ $reference = (string) Str::uuid();
+ report($e);
+
return CheckResult::error(
key: $this->key,
label: $label,
- message: "CallbackCheck '{$this->key}' encountered an error: ".$e->getMessage()
+ message: __('filament-actionguard::ui.errors.check_failed', ['reference' => $reference])
);
}
}
diff --git a/src/Checks/ConditionCheck.php b/src/Checks/ConditionCheck.php
index b82e070..2224f1c 100644
--- a/src/Checks/ConditionCheck.php
+++ b/src/Checks/ConditionCheck.php
@@ -6,6 +6,7 @@
use Allgorithm\FilamentActionGuard\Results\CheckResult;
use Closure;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Str;
class ConditionCheck implements ActionGuardCheckContract
{
@@ -69,10 +70,13 @@ public function evaluate(Model $record): CheckResult
try {
$passed = (bool) call_user_func($this->condition, $record);
} catch (\Throwable $e) {
+ $reference = (string) Str::uuid();
+ report($e);
+
return CheckResult::error(
key: $this->key,
label: $label,
- message: "ConditionCheck '{$this->key}' encountered an error: ".$e->getMessage()
+ message: __('filament-actionguard::ui.errors.check_failed', ['reference' => $reference])
);
}
diff --git a/src/Checks/MediaCheck.php b/src/Checks/MediaCheck.php
index e403165..1582aa6 100644
--- a/src/Checks/MediaCheck.php
+++ b/src/Checks/MediaCheck.php
@@ -5,6 +5,7 @@
use Allgorithm\FilamentActionGuard\Contracts\ActionGuardCheckContract;
use Allgorithm\FilamentActionGuard\Results\CheckResult;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Str;
class MediaCheck implements ActionGuardCheckContract
{
@@ -53,10 +54,13 @@ public function evaluate(Model $record): CheckResult
}
}
} catch (\Throwable $e) {
+ $reference = (string) Str::uuid();
+ report($e);
+
return CheckResult::error(
key: "media.{$this->collection}",
label: $label,
- message: "MediaCheck for '{$label}' encountered an error: ".$e->getMessage()
+ message: __('filament-actionguard::ui.errors.check_failed', ['reference' => $reference])
);
}
diff --git a/src/Checks/RelationshipCheck.php b/src/Checks/RelationshipCheck.php
index d809f0f..f4f9f7b 100644
--- a/src/Checks/RelationshipCheck.php
+++ b/src/Checks/RelationshipCheck.php
@@ -6,6 +6,7 @@
use Allgorithm\FilamentActionGuard\Results\CheckResult;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
+use Illuminate\Support\Str;
class RelationshipCheck implements ActionGuardCheckContract
{
@@ -49,10 +50,13 @@ public function evaluate(Model $record): CheckResult
try {
$relationValue = $record->getRelationValue($this->relationship);
} catch (\Throwable $e) {
+ $reference = (string) Str::uuid();
+ report($e);
+
return CheckResult::error(
key: $this->relationship,
label: $label,
- message: "Relationship '{$this->relationship}' could not be resolved: ".$e->getMessage()
+ message: __('filament-actionguard::ui.errors.check_failed', ['reference' => $reference])
);
}
diff --git a/src/Exceptions/StateInvariantViolationException.php b/src/Exceptions/StateInvariantViolationException.php
index 109018f..b6a846a 100644
--- a/src/Exceptions/StateInvariantViolationException.php
+++ b/src/Exceptions/StateInvariantViolationException.php
@@ -71,7 +71,7 @@ public static function fromResult(Model $model, string $state, ActionGuardResult
*/
public function sendNotification(): void
{
- if (! class_exists(Notification::class)) {
+ if (! config('filament-actionguard.notifications', true) || ! class_exists(Notification::class)) {
return;
}
diff --git a/src/Results/ActionGuardResult.php b/src/Results/ActionGuardResult.php
index 3093aa0..7c61e2e 100644
--- a/src/Results/ActionGuardResult.php
+++ b/src/Results/ActionGuardResult.php
@@ -17,7 +17,7 @@ public function __construct(
/**
* @param array