PackageBoundaryRule
A boundary drawn by which package owns a class, not by how the class is spelled. {@see BoundaryRule} bans namespace prefixes, which works whenever the forbidden side has a name of its own. It cannot work when the boundary runs *through* a namespace — and in this family it does: `Milpa\Live\Rendering\ComponentRendererRegistry` ships in `milpa/live`, the render-agnostic core a plugin may depend on, while `Milpa\Live\Rendering\DashboardHtmlRenderer` ships in `milpa/live-web`, one surface among several. Same prefix, opposite sides. The consequence is worse than a missing rule: the coupling does not *look* like coupling. Two import lines, identical in shape, one fine and one binding a plugin to the web. A reviewer cannot see it, and a text rule would need every surface class enumerated by hand — a list that goes stale the first time a surface adds a class, and goes stale silently. So this rule names **packages**, and the validator resolves each referenced class to the file it lives in, hence to its owner. What a plugin may use stays a question about architecture ("does * this belong to a surface?") instead of a question about strings. The rules themselves are host policy — which directories hold plugins, which packages are surfaces. This package only knows how to enforce one.
PackageBoundaryRule::__construct()
public function __construct(string $label, string $dir, array $forbiddenPackages, array $whitelist = [], array $watchedPrefixes = []):Parameters
| Name | Type | Description |
|---|---|---|
| $label | string | what this rule protects, in the words of whoever will read the failure |
| $dir | string | directory to scan, relative to the root given to the validator |
| $forbiddenPackages | list<string> | composer package names the scanned code must not reach into |
| $whitelist | list<string> | relative paths inside `$dir` exempt from the rule |
| $watchedPrefixes | list<string> | class prefixes this rule has an opinion about. Empty means all of them — strictest, and the right default for a rule that would otherwise narrow itself by accident. Naming `Milpa\\` keeps the finding about the family instead of about every vendor in the tree |