Is your feature request related to a problem? Please describe.
AttackService._persist_base64_pieces_async in pyrit/backend/services/attack_service.py has accumulated a deeply branched media-origin and persistence workflow. It currently distinguishes remote URLs, /api/media references, existing and missing local paths, data URIs, and raw base64; resolves MIME types and extensions; persists bytes; and mutates message pieces in one method.
ConverterService.preview_conversion_async handles overlapping media classification and persistence cases through a separate branch tree. Keeping these decisions parallel increases the risk that supported origins, extension handling, path validation, or failure behavior drift between backend operations. The concern is duplicated ownership and trust-boundary logic, not method size by itself.
Describe the solution you'd like
Extract a shared, typed backend media persistence component used by both services. It should:
- classify the media origin explicitly, including remote URL,
/api/media, local path, data URI, and raw base64;
- centralize MIME-type and file-extension resolution;
- preserve current allowed-path and media trust-boundary behavior;
- return a typed result rather than relying on partially completed in-place mutation;
- keep service-specific orchestration in
AttackService and ConverterService;
- preserve existing public API and error behavior unless a focused regression test proves a defect.
The extraction should delete the duplicated classification/persistence branches rather than wrapping them in pass-through helpers.
Describe alternatives you've considered, if relevant
Splitting _persist_base64_pieces_async into several private methods inside AttackService would reduce nesting but would not prevent behavior from diverging from converter preview handling. Moving all media behavior into models would also be inappropriate because filesystem validation and persistence are backend service responsibilities.
Additional context
This was identified during the September 9, 2026 repository complexity audit as the cleanest untracked standalone reduction candidate. The current method was measured at roughly 76 lines with 16 branches.
Suggested deterministic tests should cover both service paths for:
- remote URLs and
/api/media references;
- existing and missing local paths;
- valid and malformed data URIs;
- raw base64 input;
- known, missing, and conflicting MIME types/extensions;
- path-security validation;
- persistence failures and mutation/rollback behavior.
Validate the focused backend service and route suites, media DTO round trips, serializers, Ruff, typing, and git diff --check.
Is your feature request related to a problem? Please describe.
AttackService._persist_base64_pieces_asyncinpyrit/backend/services/attack_service.pyhas accumulated a deeply branched media-origin and persistence workflow. It currently distinguishes remote URLs,/api/mediareferences, existing and missing local paths, data URIs, and raw base64; resolves MIME types and extensions; persists bytes; and mutates message pieces in one method.ConverterService.preview_conversion_asynchandles overlapping media classification and persistence cases through a separate branch tree. Keeping these decisions parallel increases the risk that supported origins, extension handling, path validation, or failure behavior drift between backend operations. The concern is duplicated ownership and trust-boundary logic, not method size by itself.Describe the solution you'd like
Extract a shared, typed backend media persistence component used by both services. It should:
/api/media, local path, data URI, and raw base64;AttackServiceandConverterService;The extraction should delete the duplicated classification/persistence branches rather than wrapping them in pass-through helpers.
Describe alternatives you've considered, if relevant
Splitting
_persist_base64_pieces_asyncinto several private methods insideAttackServicewould reduce nesting but would not prevent behavior from diverging from converter preview handling. Moving all media behavior into models would also be inappropriate because filesystem validation and persistence are backend service responsibilities.Additional context
This was identified during the September 9, 2026 repository complexity audit as the cleanest untracked standalone reduction candidate. The current method was measured at roughly 76 lines with 16 branches.
Suggested deterministic tests should cover both service paths for:
/api/mediareferences;Validate the focused backend service and route suites, media DTO round trips, serializers, Ruff, typing, and
git diff --check.