UC-21 Staff send a reminder that reaches a student's in-app feed
| Primary actor | SHS Staff (Admin) |
| Supporting actors | Student; the scheduler (a CronJob on the demo tier, EventBridge Scheduler in production) |
| Priority | Should |
| Satisfies | FR-B7, FR-C8 |
| Precondition | Students are enrolled in a published challenge with notifications enabled. |
| Trigger | The scheduler proposes a reminder, or an admin composes one. |
Main success scenario
- On its cadence, the scheduler proposes draft reminders from challenge data: a week opening, a challenge ending soon. Each proposal is made once.
- An admin works the queue: send, edit then send, or skip each draft, or compose a broadcast to the whole challenge or only to students whose current week is incomplete. The queue shows the audience size.
- Approving publishes the reminder. A
scheduledrow is terminal and appears in every targeted enrolled student's in-app banner at once, for 14 days. - Every decision is audited: who approved, edited or skipped, and when.
Extensions
- 2a. The challenge is muted (
notifications_enabledfalse). Approval is refused with 409 and the challenge's reminders leave the feed. - 3a. A student dismisses a reminder. It stays dismissed for that student.
- Direct calls to the staff queue by a student are rejected as unauthorised.
- Push, device registration and opt-in preferences were retired (ADR 0002). In-app is the only channel.
Acceptance criteria (Gherkin)
| Feature file | Test module |
|---|---|
notification_scheduling.feature |
test_notification_scheduling_bdd.py |
staff_notification_queue.feature |
test_staff_notification_queue_bdd.py |
single_channel_notification_lifecycle.feature |
test_single_channel_notification_lifecycle_bdd.py |
in_app_reminder_banner.feature |
test_in_app_reminder_banner_bdd.py |
Plain pytest: test_notification_scheduling.py, test_staff_notification_queue.py, test_single_channel_notification_lifecycle.py, test_in_app_reminder_banner.py. Frontend: NotificationQueue.test.tsx, ReminderBanner.test.tsx.
Views
- Process: UC-21 A reminder reaches the feed
- Logical:
NotificationandNotificationAuditin the domain model - Physical: the scheduled notify task in production and the CronJob on the demo tier
Code: backend/app/services/notification_scheduling.py, notification_queue.py, notification_feed.py, notification_content.py, backend/app/routers/notifications_queue.py, backend/app/routers/notifications.py, frontend/src/components/admin/NotificationQueue/, frontend/src/components/ReminderBanner/. ADR 0002 records the channel decision.