feat(notify): event added and cancelled notifications #90

Merged
nalum merged 3 commits from feat/event-notifications into main 2026-08-16 12:41:12 +00:00
Owner

Stacked on #89 (merge order: #88 then #89 then this; Forgejo retargets as parents land).

Events were the one member-facing surface with no emissions at all — being added to an event or having one cancelled reached nobody's phone. Two kinds close it:

  • EVENT_ADDED tells a member someone put them on an event: at Create for everyone on the prototype, at AddUser for the one added. Never the actor themselves, and never on the idempotent re-add.
  • EVENT_CANCELLED tells the event's members — not the household — that the series was deleted or one occurrence cancelled (message carries the date). The actor is skipped, and an already-cancelled occurrence stays quiet.

Deliberately silent, recorded here as decisions: RemoveUser (being dropped from a plan is the organiser's conversation, not a push) and Update (noise).

Mechanics follow the existing shape: EventServer gains the notify seam the item server carries, emissions are post-commit best-effort, the webhook decorator forwards both as notify.event_* semantic events, messages are localized server-side (en + ga), and both kinds join the web push-preference checkboxes, the synced kind list, and the Android per-kind channels.

Verified against the live deploy on a real phone: invited to an event → "Stream Test added you to “Notification test picnic”" banner within seconds; event deleted → "Stream Test cancelled …" banner. make check green, Android build green.

🤖 Generated with Claude Code

Stacked on #89 (merge order: #88 then #89 then this; Forgejo retargets as parents land). Events were the one member-facing surface with no emissions at all — being added to an event or having one cancelled reached nobody's phone. Two kinds close it: - **EVENT_ADDED** tells a member someone put them on an event: at `Create` for everyone on the prototype, at `AddUser` for the one added. Never the actor themselves, and never on the idempotent re-add. - **EVENT_CANCELLED** tells the event's members — not the household — that the series was deleted or one occurrence cancelled (message carries the date). The actor is skipped, and an already-cancelled occurrence stays quiet. Deliberately silent, recorded here as decisions: `RemoveUser` (being dropped from a plan is the organiser's conversation, not a push) and `Update` (noise). Mechanics follow the existing shape: `EventServer` gains the notify seam the item server carries, emissions are post-commit best-effort, the webhook decorator forwards both as `notify.event_*` semantic events, messages are localized server-side (en + ga), and both kinds join the web push-preference checkboxes, the synced kind list, and the Android per-kind channels. Verified against the live deploy on a real phone: invited to an event → "Stream Test added you to “Notification test picnic”" banner within seconds; event deleted → "Stream Test cancelled …" banner. `make check` green, Android build green. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Events were the one member-facing surface with no emissions at all:
being added to an event, an event deleted, an occurrence cancelled —
all silent on every device. Two kinds close it. EVENT_ADDED tells the
member someone put them on an event (at Create for everyone on the
prototype, at AddUser for the one added — never the actor themselves).
EVENT_CANCELLED tells the event's members, except the actor, that the
series was deleted or one date cancelled. RemoveUser stays silent on
purpose — being dropped from a plan is the organiser's conversation to
have, not a push notification; Update stays silent as noise.

The EventServer gains the notify seam the item server already carries;
emissions are post-commit and best-effort as everywhere else.
The two new kinds join the push-preference checkboxes and the synced
kind list — a kind missing from PUSH_KINDS is stripped from the stored
preference on the next settings write, so every new NotificationKind
must join.
feat(android): notification channels for the event kinds
All checks were successful
check / commits (pull_request) Successful in 5s
check / web (pull_request) Successful in 1m33s
check / go (pull_request) Successful in 2m36s
check / report (pull_request) Successful in 3s
android / build (pull_request) Successful in 5m25s
android / report (pull_request) Successful in 3s
93fcf921d9
One channel per kind, as ever — the phone's own per-channel switches
line up with the two new server kinds.

Test report

Suite Tests Result Skipped
Unit 1332 ✅ pass 1
Integration 83 ✅ pass —

Coverage: 27.7%

Updated by the check workflow · commit 93fcf921d9

<!-- ci-test-report --> ## Test report | Suite | Tests | Result | Skipped | | --- | --: | --- | --: | | Unit | 1332 | ✅ pass | 1 | | Integration | 83 | ✅ pass | — | **Coverage:** 27.7% <sub>Updated by the check workflow · commit 93fcf921d9e463272bcfd6c5ca3c1ac61f2046ad</sub>

Android test report

Suite Tests Result Skipped
Unit (debug) 31 ✅ pass 0

Updated by the android workflow · commit 93fcf921d9

<!-- android-test-report --> ## Android test report | Suite | Tests | Result | Skipped | | --- | --: | --- | --: | | Unit (debug) | 31 | ✅ pass | 0 | <sub>Updated by the android workflow · commit 93fcf921d9e463272bcfd6c5ca3c1ac61f2046ad</sub>
nalum force-pushed feat/event-notifications from 93fcf921d9
All checks were successful
check / commits (pull_request) Successful in 5s
check / web (pull_request) Successful in 1m33s
check / go (pull_request) Successful in 2m36s
check / report (pull_request) Successful in 3s
android / build (pull_request) Successful in 5m25s
android / report (pull_request) Successful in 3s
to 2c966a9413
Some checks failed
check / commits (pull_request) Successful in 4s
check / go (pull_request) Successful in 3m54s
check / report (pull_request) Has been cancelled
check / web (pull_request) Has been cancelled
android / report (pull_request) Has been cancelled
android / build (pull_request) Has been cancelled
check / commits (push) Successful in 5s
check / web (push) Successful in 3m2s
tag / tag (push) Failing after 5s
check / go (push) Successful in 3m29s
check / report (push) Has been skipped
android / build (push) Successful in 13m17s
android / report (push) Has been skipped
2026-08-16 12:40:37 +00:00
Compare
nalum changed target branch from feat/matrix-sub-verbs to main 2026-08-16 12:41:08 +00:00
nalum merged commit 2c966a9413 into main 2026-08-16 12:41:12 +00:00
nalum deleted branch feat/event-notifications 2026-08-16 12:41:12 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
eagraiclainne/app!90
No description provided.