Using the guard
To check the project against the rules in mago.toml:
mago guard
To check a single directory or file:
mago guard src/Domain
mago guard src/UI/Controller/UserController.php
Paths passed on the command line replace the paths from mago.toml for that run.
Reading the output
The guard reports two kinds of issues: boundary breaches from the perimeter guard and structural flaws from the structural guard.
Boundary breach
Given this rule:
[[guard.perimeter.rules]]
namespace = "App\\Domain\\"
permit = ["@self", "@native"]
And this code:
namespace App\Domain\Model;
use App\Infrastructure\Doctrine\Orm\Entity;
class User extends Entity {}
The guard reports:
error[disallowed-use]: Illegal dependency on `App\Infrastructure\Doctrine\Orm\Entity`
┌─ src/Domain/Model/User.php:4:5
│
4 │ use App\Infrastructure\Doctrine\Orm\Entity;
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This `use` statement is not allowed by the architectural rules
│
= Breach occurred in namespace `App\Domain\Model`.
= Dependency forbidden by architectural rules
= The following rule(s) were evaluated but none permitted this dependency: `App\Domain\\`.
= Help: Update your guard configuration to allow this dependency or refactor the code to remove it.
Restricting where a dependency may be used
Perimeter restrictions protect a dependency from selected source namespaces. This rule allows the base controller to be used only by code under App\Http\Controllers\:
[[guard.perimeter.restrictions]]
dependency = "App\\Http\\Controllers\\Controller"
allow-from = ["App\\Http\\Controllers\\"]
This rule forbids an external trait throughout App\, even if an ordinary perimeter rule permits it:
[[guard.perimeter.restrictions]]
dependency = "Illuminate\\Foundation\\Bus\\Dispatchable"
deny-from = ["App\\"]
Restrictions are useful for focused bans. When no ordinary perimeter rules or layering are configured, dependencies that do not match a restriction remain allowed.
Structural flaw
Given this rule:
[[guard.structural.rules]]
on = "App\\UI\\**\\Controller\\**"
target = "class"
must-be-final = true
reason = "Controllers should be final to prevent extension."
And this code:
namespace App\UI\Controller;
class UserController
{
}
The guard reports:
error[must-be-final]: Structural flaw in `App\UI\Controller\UserController`
┌─ src/UI/Controller/UserController.php:3:7
│
3 │ class UserController
│ ^^^^^^^^^^^^^^ This must be declared as `final`
│
= Controllers should be final to prevent extension.
= Help: Declare this class as `final`.
Each report identifies the symbol, the location, the exact violation, and the reason from the configuration when one was provided.
Limiting public methods
Use only-public-methods to limit the directly declared public API of matched classes:
[[guard.structural.rules]]
on = "App\\Http\\Controllers\\**"
target = "class"
only-public-methods = ["__construct", "__invoke"]
Any other directly declared public method produces an only-public-methods flaw. Private and protected methods remain allowed. The configured names are allowed, not required, and inherited or trait-provided methods are not checked.