Skip to content

feat(sniffs): close bypass loopholes in Service and ValueObject sniffs#54

Merged
prikotov merged 1 commit into
masterfrom
task/close-sniff-bypass-loopholes
May 22, 2026
Merged

feat(sniffs): close bypass loopholes in Service and ValueObject sniffs#54
prikotov merged 1 commit into
masterfrom
task/close-sniff-bypass-loopholes

Conversation

@prikotov
Copy link
Copy Markdown
Owner

Проблема

Обнаружены два способа обойти существующие сниффы:

1. ServiceStructureSniff — обход через удаление Service\ из пути

Класс NullNotificationBroadcaster реализует интерфейс из Domain\Service\, но лежит в Integration\Broadcaster\ (без Service\ в пути). Sniff его пропускал, потому что:

  • inServiceDir = false (нет Service в пути)
  • hasSuffix = false (нет суффикса Service)

Оба условия false → sniff молчал.

2. ValueObjectStructureSniff — VO без суффикса Vo

Класс RuntimeContext в namespace Domain\ValueObject\ — без суффикса Vo. Sniff проверял только классы с суффиксом Vo, остальные полностью пропускал.

Решение

ServiceStructureSniff

Новое правило DomainServiceImplOutsideServiceDirectory: если класс реализует интерфейс из Domain\Service\ (через use или FQCN) — он обязан лежать в директории Service/.

Sniff парсит use-statements для определения FQCN интерфейсов из implements.

ValueObjectStructureSniff

Новое правило MissingVoSuffix: если класс находится в namespace \ValueObject\ или \Vo\, но не имеет суффикса Vo — ошибка.

Тесты

Фикстура Ожидание
NullNotificationBroadcaster.incimplements через use, вне Service/ ошибка
FqcnBroadcaster.incimplements через FQCN, вне Service/ ошибка
LogOnSomethingListener.inc — вне Service/, интерфейс не из Domain\Service\ проходит
RuntimeContext.inc — в ValueObject\ namespace без суффикса Vo ошибка
EmailVo.inc — в ValueObject\ namespace с суффиксом Vo проходит

Чек-лист

  • composer check пройден
  • Новые тест-фикстуры добавлены
  • PHPStan baseline обновлён

- ServiceStructureSniff: detect classes implementing Domain\Service\ interface
  outside Service/ directory (DomainServiceImplOutsideServiceDirectory error).
  Prevents bypass by removing Service\ segment from namespace path.

- ValueObjectStructureSniff: require Vo suffix for classes in ValueObject/Vo
  namespace (MissingVoSuffix error). Prevents creating VO without proper naming
  convention like RuntimeContext instead of RuntimeContextVo.
@prikotov prikotov merged commit cf0da26 into master May 22, 2026
3 checks passed
@prikotov prikotov deleted the task/close-sniff-bypass-loopholes branch May 22, 2026 15:26
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.

1 participant