symfony-hexagonal-architecture — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited symfony-hexagonal-architecture (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are an expert in Symfony hexagonal architecture (ports & adapters). Use this skill when users need to set up project structure, create new modules, or understand layer responsibilities.
Before generating any code, know the project's Symfony, PHP, Doctrine and PHPUnit versions (the plugin's SessionStart hook prints them; otherwise read composer.lock). Then follow references/version-compatibility.md:
DeduplicateStamp, 7.4 #[ExtendsValidationFor], PHP 8.4 private(set), ...) only when the detected versions allow itRequest::get(), constraint option arrays, XML service config)Presentation → Application → Domain ← InfrastructureInfrastructure depends on Domain (implements ports), but Domain NEVER depends on Infrastructure.
Every module follows this structure under src/:
Domain/{Module}/
├── Entity/ # Aggregates and entities (pure PHP)
├── ValueObject/ # Immutable value objects
├── Event/ # Domain events (past-tense)
├── Exception/ # Domain-specific exceptions
├── Port/ # Interfaces for external dependencies (write + read ports)
└── ReadModel/ # (optional) Plain read-side view objects returned by read ports
Application/{Module}/
├── Command/ # Write operations (final readonly) + handlers
├── Query/ # Read operations (final readonly) + handlers
├── DTO/ # Data transfer objects
└── EventHandler/ # Domain event handlers (side-effects)
Infrastructure/{Module}/
├── Persistence/ # Doctrine repositories, Mapping/*.orm.xml
├── Security/ # Voters, user providers
├── Messaging/ # Transport adapters, middleware
└── ExternalService/ # HTTP clients, third-party APIs
Presentation/{Module}/
├── API/ # REST controllers (+ Request/ DTOs)
├── CLI/ # Console commands
└── GraphQL/ # GraphQL resolvers/typesShared code lives in a Shared module per layer (Domain/Shared/ValueObject/Money.php, Presentation/Shared/Bus/QueryBus.php, ...).
When working on an existing project that doesn't follow hexagonal architecture:
Before writing any code, check:
- Is src/ organized by layer (Domain/, Application/, etc.) or by traditional Symfony (Controller/, Entity/, Repository/)?
- Does the module the user is working on already follow hexagonal patterns?
- Are there Doctrine annotations/attributes directly on entities?
- Which Symfony / Doctrine versions are installed (affects what the refactor can use)?When the user requests a feature/change in a non-hexagonal module, ALWAYS ask:
"Bu modül ({Module}) şu anda hexagonal yapıda değil. Şu seçeneklerden birini tercih edebilirsiniz: 1. Önce refactor:{Module}modülünü hexagonal mimariye taşıyıp, sonra yeni özelliği ekleyeyim 2. Sadece yeni kodu hexagonal yap: Mevcut koda dokunmadan, yeni eklenen kısımları hexagonal yapıda oluşturayım 3. Mevcut yapıda devam et: Bu sefer hexagonal yapıyı atlayalım
>
Hangisini tercih edersiniz?"
Migrate one layer at a time, in this order:
Domain/{Module}/Entity/, create value objects, define port interfacesInfrastructure/{Module}/Persistence/, move mapping from attributes/annotations to XMLApiResponseTrait + #[MapRequestPayload] DTOs, apply #[IsGranted]After each layer, verify the code still works (tests + doctrine:schema:validate) before moving to the next.
Legacy projects on Doctrine annotations (@ORM\...) cannot upgrade to ORM 3 anyway: moving the mapping to XML during the Infrastructure step unblocks that upgrade too.
When user asks to create a new module, generate ALL directories and base files:
Domain/{Module}/Port/Infrastructure/{Module}/Persistence/doctrine.yaml and bind ports to adapters in services.yamluse Symfony\..., use Doctrine\... or use Psr\... in any Domain file, and no framework attributes (#[ORM\...], #[Assert\...], #[AsMessage])App\Domain\{Module}\..., App\Application\{Module}\..., etc.references/dependency-rules.md)See references/ for detailed guides:
version-compatibility.md - Symfony / PHP / Doctrine / PHPUnit support matrix, per-feature minimum versions and fallbacksdirectory-structure.md - Full directory layout with file exampleslayer-responsibilities.md - What belongs in each layerdependency-rules.md - Import rules, deptrac and PHPStan enforcement~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.