feat: #3612558 Carry file attachments on OrchestraNotificationEvent and honor them in the mail channels
Fixes #3612558.
Summary
Adds file-attachment support to the channel-neutral OrchestraNotificationEvent, so a dispatcher can deliver generated files (a PDF ticket, a calendar invite, a receipt) alongside a notification. The driving consumer is the Yoyaku ticket submodule, which attaches per-order ticket PDFs to the confirmation email.
What changed
NotificationAttachment(@api,Drupal\orchestra): an immutable value object holding a filename, a MIME type and its source as either raw content or a stream-wrapper URI, via::fromContent()/::fromUri(). It stays transport neutral, exposing only the file's data, so each channel maps it to its own wire format (a future SMS, WhatsApp or chat channel maps the same object).OrchestraNotificationEventgains a trailingarray $attachments = [](backward compatible).orchestra_mailmaps each attachment to the Drupal mail attachment array and delivers it throughparams['attachments'].orchestra_easy_emaildoes the same at the mail layer (via the channel's existing mail alter), not on the Easy Email entity, so a private file (a ticket PDF inprivate://) is never subject to Easy Email's attachment-path allowlist, whose default permits onlypublic://.
Each channel owns its own mapping, so the neutral contract never learns a transport format.
Tests
- Unit: the value object's factories and content-vs-URI exclusivity.
- Kernel, per channel: present vs empty attachments, content vs URI, and multiple files, asserting the exact mail-attachment shape and that the private carrier key is consumed.
Docs
Updated docs/notification-delivery.md (event schema and an Attachments section) and both channel READMEs.