Skip to content

Send report packets with media links only (#138) - #120

Merged
theobong merged 1 commit into
mainfrom
fix/packet-links-not-attachments
Sep 24, 2026
Merged

theobong merged 1 commit into
mainfrom
fix/packet-links-not-attachments

Conversation

@theobong

Copy link
Copy Markdown
Member

Part of civfix/issue-tracker#138

What changed

A report sent to a city no longer carries its photos as email attachments. The email lists every photo and video as a link instead, so a strict mail server has nothing to block. Admin only: this changes the email the city receives, not any screen.

Before you start

  • Where: staging (admin.civfix.dev)
  • Sign in as: operator
  • Data: a report with at least two photos and one video, not yet sent, whose jurisdiction's routing contact is an inbox you can read
  • Size: 328 counted lines, 278 of them deletions: one removed send path plus its tests, with nothing left to split off

Verify

[Admin]

  1. Open "Reports" and select the report.
  2. Click "Send to jurisdiction", then "Send" in the "Send to the city?" dialog. — Expect: the toast "Sent to ".
  3. Open the email in the contact's inbox. — Expect: no attachments. The body lists "Photo 1", "Photo 2" and "Video 1", each with a link.
  4. Open each link. — Expect: each one loads its photo or video.

Regression

Resend from Mail — [Admin]

  1. Open "Mail" and open the conversation for the report you just sent.
  2. Click "Resend". — Expect: a second copy arrives with the same text and links and no attachments.
  3. Open the conversation for a report sent before this change, if one exists, and click "Resend". — Expect: the copy arrives with links and no attachments. The older message in the thread still shows the attachment names it was stored with.

Follow-up to the city — [Admin]

  1. On the same report, type a message in the box under the city name.
  2. Click "Send to city". — Expect: the toast "Follow-up sent to city", and the email arrives in the same conversation with no attachments.

City replies with files — [Admin]

  1. Reply to the report email from the contact's inbox and attach a file.
  2. Open the conversation in "Mail". — Expect: the reply shows its attachment, as before.

Not covered

  • The admin "Send to the city?" dialog still says the email includes "its attached photos". That copy lives in civfix-admin and needs its own change.
  • Auto-forwarded reports take the same send path. They are covered by unit tests, not by a manual step.

@theobong
theobong merged commit bbb49ea into main Sep 24, 2026
3 checks passed
@theobong
theobong deleted the fix/packet-links-not-attachments branch September 24, 2026 03:13
@greptile-apps

greptile-apps Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

Not merge-safe: report resends can deliver expired media links and leave recipients unable to access the referenced report media.

Fix All in Claude CodeFindings

  1. P1 Refresh resend media links ▶
Fix with agent prompt
### Issue 1
services/api/src/services/admin/mail-service.ts:135-139
Report packets store signed private-media URLs in their text and HTML. This resend path forwards those stored bodies unchanged, so a resend after the seven-day URL lifetime sends links that can no longer retrieve the report photo or video; attachments are no longer included as a fallback. Rebuild report packet links from durable media keys, or retain structured media metadata and mint fresh URLs before delivery. This must be fixed before merging.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1) · Last reviewed commit: "send report packets with media links onl..."

Comment on lines 135 to 139
await outboundMail.appendOutbound(id, {
body: last.body,
toAddr,
...(subject.length > 0 ? { subject } : {}),
...(last.html !== null ? { html: last.html } : {}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Refresh resend media links

Report packets store signed private-media URLs in their text and HTML. This resend path forwards those stored bodies unchanged, so a resend after the seven-day URL lifetime sends links that can no longer retrieve the report photo or video; attachments are no longer included as a fallback. Rebuild report packet links from durable media keys, or retain structured media metadata and mint fresh URLs before delivery. This must be fixed before merging.

Artifacts

Expired packet link reproduction script

  • The focused script creates a private-media report packet and resends it after the modeled link expiry, demonstrating whether the stored URL is refreshed.

Expired packet link reproduction command

  • The command wrapper executes the focused packet generation and resend reproduction.

Original private report packet generation

  • Executed the focused service script to generate the original report packet; it shows one private-media presign from the durable key and the signed URL in the stored text body, establishing the before condition.

Resend after modeled link expiry

  • Executed the focused service script to resend after the seven-day modeled expiry; it shows no refresh call and the expired signed URL remains in the resent body, confirming the defect.

Expired packet link command output

  • The command completed successfully and records that the expired signed URL remained in both resent text and HTML without a refresh.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: services/api/src/services/admin/mail-service.ts
Line: 135-139

Comment:
**Refresh resend media links**

Report packets store signed private-media URLs in their text and HTML. This resend path forwards those stored bodies unchanged, so a resend after the seven-day URL lifetime sends links that can no longer retrieve the report photo or video; attachments are no longer included as a fallback. Rebuild report packet links from durable media keys, or retain structured media metadata and mint fresh URLs before delivery. This must be fixed before merging.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant