th0masso/ssacc-bundle
Symfony bundle for SSACC, providing a lightweight integration with Symfony’s service container and security layer. It makes defining and enforcing access rules for routes, controllers, and services straightforward with minimal configuration.
Before anything else: this is still a Symfony bundle, not a Laravel package. composer require th0masso/ssacc-bundle in a Laravel app will resolve but do nothing — its service provider wiring, command registration, and config loading assume Symfony's Kernel, security-bundle, and config/bundles.php. Treat it as a tool you run in a Symfony codebase (side project, inherited service, client repo), or as a reference implementation for an equivalent Artisan command.
Minimal steps in a Symfony project:
composer require th0masso/ssacc-bundle (pin the exact version — see Gotchas; v1.0.0 is the first tagged release, so treat the API as unstable).config/bundles.php; otherwise add Th0masso\SsaccBundle\SsaccBundle::class => ['all' => true].vendor/th0masso/ssacc-bundle/ for the sample config (likely under config/ or Resources/config/) and copy it into your project — e.g. config/ssacc.yaml — rather than editing anything in vendor/.bin/console list | grep -i ssacc. The exact command name lives in the README on GitHub and in src/Command/ — verify both rather than guessing.bin/console <command> config/ssacc.yamlWhere to look first: the README, then the bundle's Command class and its DependencyInjection/ extension — you need to know which config keys have defaults and which are required, because the release notes only name them. There are only a handful of files; reading all of src/ takes minutes and is worth doing before you wire it into CI.
First use case: an audit of an existing app to surface routes with no security rule, and access_control entries referencing roles or paths that no longer exist. Run it with a config scoped to one controller directory, read the report, and ignore the exit code until you trust the output.
Commit the config, not the invocation flags. The v1.0.0 config file is the whole interface now. Check config/ssacc.yaml into the repo so the checker behaves identically on every dev machine and in CI, and so changes to what you consider "secure" are reviewable diffs.
CI gate (the pattern worth stealing). Add the command to a GitHub Actions / GitLab CI job and let a non-zero exit code fail the build. This turns "someone forgot a security rule on the new admin route" into a red pipeline instead of a pentest finding. Start non-blocking (report only), fix the baseline, then flip it to blocking.
Baseline / allowlist is now built in. exclude_all_routes_that_start_with and exclude_full_routes replace the hand-rolled allowlist pattern. Keep the exclusion list checked in, keep it short, and review additions to it like you'd review a // phpcs:ignore — every entry is a decision that this route is intentionally public. Prefer exclude_full_routes (exact matches) over prefix exclusions wherever the route name or path is stable; prefixes rot silently.
Scope per team or per app in monorepos. project_path and controllers_path let you point the checker at a single bundle or sub-application. The useful pattern in a multi-app repo is one config file per app plus one CI job per config, rather than one giant config that flags everything at once.
Tune security_requirement deliberately. Whatever this key encodes (the role/guard a route is expected to require, as named), set it to what your organisation treats as the minimum — it is the single knob that determines how many findings you get. Set it too strictly on the first run and you'll drown in noise and turn the gate off.
Ordering still matters in Symfony. access_control is first-match-wins, so a broad path: ^/ rule above a specific path: ^/admin silently shadows the latter. The checker flags the symptom; the ordering in security.yaml is usually the cause. Always cross-read the file next to the report.
Laravel translation of the same idea. The direct equivalent is an Artisan command or a Pest/PHPUnit architecture test that walks Route::getRoutes(), inspects each route's middleware (auth, can:, custom gates) and controller #[Middleware]/authorize() calls, and asserts that anything under a privileged prefix has a guard. That's ~80 lines and removes the dependency entirely. If you like this package's output format, mirror it; don't try to shim the bundle into Laravel.
Attribute-aware review. controllers_path suggests v1.0.0 does scan controller code, not just security.yaml — verify what it actually inspects before assuming coverage. If your app relies on #[IsGranted] and voters, confirm the checker reads them; if it doesn't, pair it with a code-level review or a test-level AccessDecisionManager assertion.
exclude_all_routes_that_start_with is prefix-based and will swallow every future route under that prefix, including the new admin route someone adds next quarter. Audit the list each time you touch it.composer.json; be prepared to fork.symfony-security-access-control-checker, packagist name is th0masso/ssacc-bundle. Confirm both before copy-pasting install instructions into a runbook.DependencyInjection/Configuration tree in the source, not from guesswork — a wrongly-shaped list key often fails silently or matches nothing.PUBLIC_ACCESS, firewall-less routes, vendor bundle routes, and dynamically registered routes all trip naive checks. Verify a handful of findings by hand before trusting the count.bin/console debug:container --tag=console.command, verify the bundle is in bundles.php, and run bin/console cache:clear — config changes in Symfony are cached and a stale container will happily use last week's settings.|| exit 1 on a grep if necessary.#[IsGranted]" or "route name under admin_ lacks a firewall." With this dependency footprint a fork is cheaper than upstream contributions — and given v1.0.0 just landed, your fork will diverge quickly.How can I help you explore Laravel packages today?