Problem
Archetype has unique constraints on both name (uniq_archetype_name) and slug (uniq_archetype_slug) at the DB level (src/Entity/Archetype.php:28-29). Soft-deleted rows (deletedAt set, src/Entity/Archetype.php:82-83) still occupy those unique keys, so an admin who deletes an archetype and tries to recreate one with the same name/slug hits a constraint violation. The admin list excludes soft-deletes (['deletedAt' => null] in AdminArchetypeController) so the conflict is invisible from the UI.
Scope
On archetype create (and on update if the new name/slug collides with a soft-deleted row), automatically rename the conflicting soft-deleted row by appending a uniqueness suffix to both its name and slug so the new archetype can take the canonical values.
Suffix shape: __deleted_<short-uniq> — e.g. Gardevoir ex → Gardevoir ex__deleted_a1b2c3 and gardevoir-ex → gardevoir-ex__deleted_a1b2c3. Generate the short id with bin2hex(random_bytes(3)) (6 hex chars, deterministic length) or Symfony\Component\Uid\Ulid truncated — match whatever the codebase already uses.
Recreate-on-create only: don't repurpose this for any other lookup.
Acceptance criteria
- Creating an archetype whose
name matches a soft-deleted archetype succeeds; the soft-deleted row is renamed with the suffix on both name and slug.
- Same for
slug (e.g. two different display names that slugify to the same value).
- Rename happens in the same transaction as the create — no partial state if the create fails.
- Admin list still shows only non-deleted rows.
- Soft-deleted renamed rows remain restorable for audit (the suffix is appended, the original prefix is preserved for inspection).
- Unit/functional test under
tests/ covering: (a) name collision, (b) slug collision via differing names, (c) no collision still works unchanged.
docs/features.md gains an F2.27 row under §F2.
Key files
src/Entity/Archetype.php — unique constraints, soft-delete column, PrePersist/PreUpdate slug generator.
src/Form/ArchetypeFormType.php — current form (no UniqueEntity validator today).
src/Controller/AdminArchetypeController.php — create/edit flow.
src/Repository/ArchetypeRepository.php — add a findSoftDeletedByNameOrSlug() helper.
tests/Entity/ArchetypeTest.php — existing test file to extend.
Notes
- Don't introduce a
UniqueEntity Symfony validator before this fix — it would also fire on the soft-deleted row and re-introduce the block at validation time. The rename must happen before the new row is flushed.
- Consider a dedicated
ArchetypeNameCollisionResolver service for testability.
Problem
Archetypehas unique constraints on bothname(uniq_archetype_name) andslug(uniq_archetype_slug) at the DB level (src/Entity/Archetype.php:28-29). Soft-deleted rows (deletedAtset,src/Entity/Archetype.php:82-83) still occupy those unique keys, so an admin who deletes an archetype and tries to recreate one with the same name/slug hits a constraint violation. The admin list excludes soft-deletes (['deletedAt' => null]inAdminArchetypeController) so the conflict is invisible from the UI.Scope
On archetype create (and on update if the new name/slug collides with a soft-deleted row), automatically rename the conflicting soft-deleted row by appending a uniqueness suffix to both its
nameandslugso the new archetype can take the canonical values.Suffix shape:
__deleted_<short-uniq>— e.g.Gardevoir ex→Gardevoir ex__deleted_a1b2c3andgardevoir-ex→gardevoir-ex__deleted_a1b2c3. Generate the short id withbin2hex(random_bytes(3))(6 hex chars, deterministic length) orSymfony\Component\Uid\Ulidtruncated — match whatever the codebase already uses.Recreate-on-create only: don't repurpose this for any other lookup.
Acceptance criteria
namematches a soft-deleted archetype succeeds; the soft-deleted row is renamed with the suffix on bothnameandslug.slug(e.g. two different display names that slugify to the same value).tests/covering: (a) name collision, (b) slug collision via differing names, (c) no collision still works unchanged.docs/features.mdgains an F2.27 row under §F2.Key files
src/Entity/Archetype.php— unique constraints, soft-delete column,PrePersist/PreUpdateslug generator.src/Form/ArchetypeFormType.php— current form (noUniqueEntityvalidator today).src/Controller/AdminArchetypeController.php— create/edit flow.src/Repository/ArchetypeRepository.php— add afindSoftDeletedByNameOrSlug()helper.tests/Entity/ArchetypeTest.php— existing test file to extend.Notes
UniqueEntitySymfony validator before this fix — it would also fire on the soft-deleted row and re-introduce the block at validation time. The rename must happen before the new row is flushed.ArchetypeNameCollisionResolverservice for testability.