Previously every "Email to vendor" click re-rendered the PO via PdfService and
re-uploaded to R2 under a timestamped key — wasteful, and it orphaned a new
object each time.
Now the PDF is stored at a deterministic per-PO key (buildPoPdfKey →
po-pdf/<poId>/<slug>.pdf). On each send, statObject() checks for an existing
copy: if it exists and is at least as new as the PO's updatedAt, it's reused
(no re-render, no re-upload) and only a fresh presigned URL is minted —
refreshing the 7-day download timer. It re-renders only when there's no copy
yet or the PO changed since the cached one (so an edited PO never emails a
stale PDF).
- lib/storage.ts: buildPoPdfKey (deterministic) + statObject (HEAD/stat, no
body transfer; null when absent).
- email-actions.ts: reuse-or-render decision keyed on updatedAt; always
re-presign.
- Tests: +2 (reuse-on-second-send-only-refreshes-link, re-render-when-changed).
email-vendor suite 8 green; tsc clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>