Migrate richer channels onto the shared notification formatter #14
Labels
No labels
area:ai
area:ci-cd
area:notifications
area:observability
area:public-pages
backlog
bug
duplicate
enhancement
help wanted
invalid
question
type:decision
type:feature
type:infra
type:maintenance
type:security
v1.0.1
v1.1.0
v1.2.0
v1.3.0
v2.0.0
wontfix
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
rbrooks/WeatherBot#14
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Target release: v1.2.0
SMS already uses the shared formatter and 140-char budget. Gradually move the richer channels (Discord, Matrix, Signal, Pushover, Webex, Webhook) onto
app/services/notification_formatting.pywith per-channel budgets/profiles and truncation metadata.Acceptance
Source:
docs/ROADMAP.md→ Notification Message Budget and Compact Link System.Audit note (2026-07-18)
From the 2026-07 codebase audit (
docs/.internal/report-2026-07-17.md), finding F-32.The shared formatter's budget math is codepoint-based —
len()against a flat 140 (app/services/notification_formatting.py:35-43,95-117). A single non-GSM-7 character (em dash, curly quote — both common in NWS text, or in a free-textlocation.name) silently flips carrier encoding to UCS-2 (70 chars/segment), so a message the code considers "fits in budget" can span 2+ real SMS segments.As part of the per-channel budgets in this issue, make the SMS budget segment-aware (detect GSM-7 vs UCS-2 and budget accordingly), or strip/replace non-GSM-7 characters before budgeting.
Related audit work now scheduled in this milestone (v1.2.0): delivery outbox (#50), pipeline concurrency (#53), per-type channel-config validation (#55), non-blocking Twilio (#56).
Done in #99 (merged). The six richer channels (Discord, Matrix, Signal, Pushover, Webex, webhook) now build messages through the shared formatter with per-channel-type budgets and a 3-tier
compose()(required / droppable-optional / pinned) that keeps one compact "Details" link in a predictable place.FormattedMessagecarries char/link/omitted/encoding/segment metadata. SMS budgeting is segment-aware (F-32: sanitize non-GSM-7 punctuation, else budget at the UCS-2 rate). Each channel's structural shape (Discord embed, Matrix HTML body, Pushover title/url, Webex markdown) is preserved.