Three threads from the recent UX iteration:
1. Reminder list / detail no longer shows raw "Cron: 32 11 * * *"
----------------------------------------------------------------
`describeRecurrence` for a kind=cron spec used to emit
"Cron: <expr>" verbatim, which is unreadable on the list row's
recurrence line.
New pure helper `describeCronRule(rule)` parses the cron shapes
the recurrence picker produces and renders them as natural
sentences:
"0 9 * * *" → "Every day at 09:00"
"0 9 * * 1-5" → "Every week on Mon, Tue, Wed, Thu, Fri at 09:00"
"0 9 * * 1,3,5" → "Every week on Mon, Wed, Fri at 09:00"
"0 9 1,15 * *" → "Every month on days 1, 15 at 09:00"
"0 9 13 5 *" → "Every year in May on day 13 at 09:00"
"30 17 1,15 1,4,7,10 *" → "Every year in Jan, Apr, Jul, Oct on days 1, 15 at 17:30"
Multi-line rules ("0 9 * * 1\n0 17 * * 5") join the per-line
descriptions with " · " for compactness in the list density.
Long DOM lists (>6 days) collapse with a "+N more" tail to keep
the line short; same convention the picker's per-row preview uses.
Unrecognised shapes (e.g. "*/5 * * * *") fall back to the raw
expression — better than swallowing entirely.
2. HEIC/AVIF magic-byte sniffing at upload
----------------------------------------------------------------
The mime-only check we shipped earlier missed iOS Safari's
habit of uploading HEIC photos with Content-Type: image/jpeg.
The file then made it to the bot, where Sharp's HEIF decoder
plugin is missing, the thumbnail extraction failed, and the
message went out without a working preview — read by the user
as "image still not send".
New helper `sniffUnsupportedImage(bytes)` reads bytes 4..11 of
the upload and looks for the ISOBMFF "ftyp" marker followed by
one of the brands Sharp can't decode (HEIF: heic / heix / hevc
/ heim / heis / mif1 / msf1; AVIF: avif / avis). Brand match is
case-insensitive. Plain JPEG / PNG / unrelated ftyp brands like
mp4 are not flagged.
`uploadMediaAction` now runs the sniff against the buffered
bytes before persisting, returning the same "Images are not
supported, please re-upload images" error as the mime path.
3. Sidebar brand link → dashboard tests
----------------------------------------------------------------
Asserts the desktop <aside> contains an <a href="/" aria-label=
"Go to dashboard"> at the top, scoped via a new extractSidebar
helper so it can't accidentally match the mobile-header brand
link (which uses aria-label="Go home"). A second test confirms
the two aria-labels stay distinct.
22 web test files / 232 passing (was 212):
- +12 cron-description cases in lib/recurrence.test.ts
- +6 magic-byte sniff cases in lib/whatsapp-media.test.ts
- +2 sidebar-brand-link cases in app-shell.test.tsx
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>