# Product Requirements Document: System Alerts

## Validation Checklist

- [x] All required sections are complete
- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Problem statement is specific and measurable
- [x] Problem is validated by evidence (not assumptions)
- [x] Context → Problem → Solution flow makes sense
- [x] Every persona has at least one user journey
- [x] All MoSCoW categories addressed (Must/Should/Could/Won't)
- [x] Every feature has testable acceptance criteria
- [x] Every metric has corresponding tracking events
- [x] No feature redundancy (check for duplicates)
- [x] No contradictions between sections
- [x] No technical implementation details included
- [x] A new team member could understand this PRD

---

## Product Overview

### Vision

A unified notification and alert system that enables BuyerKiosk administrators to instantly communicate important messages to all staff across any store, with full acknowledgment tracking and realtime delivery — while consolidating existing notification patterns (like chat toasts) into a single, consistent notification framework.

### Problem Statement

Today, BuyerKiosk has no mechanism for platform administrators to broadcast urgent or informational messages to store staff. When policy changes, system maintenance windows, feature announcements, or urgent operational alerts need to reach users, there is no in-app channel to deliver them. Admins must rely on external communication (email, phone calls, group texts) which is slow, unreliable, and untrackable. There is no way to confirm whether staff have actually seen a critical message.

Additionally, the existing chat notification toast is a standalone implementation that cannot be reused for other notification types, creating inconsistency as new realtime features are added.

### Value Proposition

System Alerts gives BuyerKiosk admins a single, authoritative channel to reach every user instantly. Messages arrive in realtime via Ably without page reloads, display as highly visible banners or persistent toasts, and the system tracks exactly who has acknowledged each alert. This eliminates communication gaps, ensures compliance-critical messages are provably delivered, and establishes a unified notification framework that consolidates chat notifications and supports future realtime features.

## User Personas

### Primary Persona: BuyerKiosk Administrator
- **Demographics:** Platform administrators with full system access (`uri_bkadmin` permission). Typically company owners or operations managers overseeing multiple stores.
- **Goals:** Communicate time-sensitive information to all store staff quickly and reliably. Confirm that critical messages have been seen. Manage alert lifecycle (create, edit, deactivate, expire).
- **Pain Points:** No in-app broadcast mechanism. No way to verify staff saw a message. Relies on external channels (email, text) which are fragmented and untrackable. Cannot target messages to specific stores.

### Secondary Persona: Store Staff Member
- **Demographics:** Store-level users who interact with admin pages and/or the workbook daily. Varying technical comfort levels. May work across multiple stores.
- **Goals:** Stay informed about policy changes, maintenance windows, urgent operational updates, and new features without interrupting their workflow.
- **Pain Points:** Important messages get lost in email or group texts. No central place to review past announcements. Notifications from different systems (chat, alerts) look and behave differently.

## User Journey Maps

### Primary User Journey: Admin Creates and Monitors an Alert

1. **Awareness:** Admin identifies a need to communicate something to staff — a policy change, upcoming maintenance window, urgent safety notice, or feature announcement.
2. **Creation:** Admin navigates to BuyerKiosk > System Alerts in the admin panel. They compose a message using the rich text editor, set severity (Info/Warning/Critical), choose display type (banner or toast), select targeting (all stores or specific stores), optionally add a CTA button with a link, and optionally set an expiry date.
3. **Publishing:** Admin clicks "Publish." The alert is immediately saved and broadcast via Ably to all targeted users currently online. Users not online will see it on their next page load.
4. **Monitoring:** Admin views the acknowledgment dashboard showing how many users have dismissed the alert, who specifically has and hasn't acknowledged it, and when each acknowledgment occurred.
5. **Lifecycle Management:** Admin can edit the alert (which resets all acknowledgments so everyone sees the updated version), deactivate it immediately, or let it auto-expire on the set date.

### Secondary User Journey: Staff Member Receives and Acknowledges Alerts

1. **Notification Arrival:** Staff member is working in the admin panel or workbook. A new alert arrives in realtime — either a banner slides in at the top of the page or a toast appears in the corner, depending on the alert's display type.
2. **Reading:** Staff member reads the alert message. If it has a CTA button, they can click it to navigate to relevant content (e.g., a policy document).
3. **Acknowledgment:** Staff member closes the alert by clicking the dismiss/close button. This is recorded as an acknowledgment and the alert will not reappear for this user.
4. **Queue Processing:** If more than 3 alerts are pending, the next alert in the queue appears after dismissal. This continues until all alerts are acknowledged.
5. **History Review:** Staff member can click the alert bell icon in the navbar to review past dismissed alerts and any current pending alerts at any time.

### Tertiary User Journey: Chat Toast via Unified System

1. **Incoming Message:** A customer sends an SMS/chat message to the store.
2. **Notification:** The unified toast system renders a "Chat" type toast with the customer name and message preview, using the chat-specific icon and color.
3. **Interaction:** Staff member clicks the toast, which opens the chat thread (preserving all current chat notification behaviors: click-to-thread, message consolidation, sound chime, orphan handling).
4. **Dismissal:** Toast is dismissed from the DOM only — no database acknowledgment tracking for chat notifications.

## Feature Requirements

### Must Have Features

#### Feature 1: Alert Creation Interface
- **User Story:** As a BuyerKiosk administrator, I want to create system alerts with a rich text editor so that I can communicate formatted messages to staff across stores.
- **Acceptance Criteria:**
  - [ ] Only users with `uri_bkadmin` permission can access the System Alerts page
  - [ ] Form includes: title (required, max 255 chars), message body (rich text with bold, italic, links, lists), severity selector (Info/Warning/Critical), display type selector (Banner or Toast), store targeting (All Stores or multi-select specific stores), optional CTA button (label + URL), optional expiry date/time
  - [ ] Rich text editor supports: bold, italic, links, ordered/unordered lists. No images, tables, or custom HTML. Content renders identically in banner and toast modes.
  - [ ] Publishing saves the alert and immediately broadcasts via Ably
  - [ ] Form validates all required fields before allowing publish
  - [ ] Published alert appears in the alerts management list immediately

#### Feature 2: Realtime Alert Delivery via Ably
- **User Story:** As a store staff member, I want to receive new alerts in realtime without refreshing the page so that I see urgent messages immediately.
- **Acceptance Criteria:**
  - [ ] New alerts appear within 2 seconds of publishing on all connected clients
  - [ ] Alerts targeted to "All Stores" are received by every connected user
  - [ ] Alerts targeted to specific stores are received by users assigned to those stores (based on `userStoreAssignments`), regardless of which store page they are currently viewing
  - [ ] Users who are offline or not on the page see pending alerts on their next page load (database is source of truth)
  - [ ] Ably connection failure does not break the page — alerts fall back to page-load delivery

#### Feature 3: Banner Display Mode
- **User Story:** As a store staff member, I want to see important alerts as a banner at the top of the page so that they are highly visible without blocking my work.
- **Acceptance Criteria:**
  - [ ] Banners appear above the page header in a consistent global position (both admin pages and workbook)
  - [ ] Banners show severity indicator (color-coded: blue for Info, yellow for Warning, red for Critical)
  - [ ] Banners display title, message body (rich text rendered), optional CTA button, and a close/dismiss button
  - [ ] Maximum 3 notifications visible at any time globally (banners + toasts combined); additional notifications queue and appear as visible ones are dismissed
  - [ ] Dismissing a banner records acknowledgment and reveals the next queued notification (if any)
  - [ ] Banners push page content down — no element overlays primary action buttons on admin or workbook pages

#### Feature 4: Toast Display Mode
- **User Story:** As a store staff member, I want to see less-intrusive alerts as toast notifications so that I'm informed without losing my place on the page.
- **Acceptance Criteria:**
  - [ ] Toasts appear in a fixed corner position (bottom-right, consistent with existing chat toast location)
  - [ ] Toasts show severity indicator (color-coded), title, message preview, optional CTA button, and close button
  - [ ] All toasts persist until manually closed (no auto-dismiss regardless of severity)
  - [ ] Toasts share the global max-3-visible limit with banners; additional notifications queue and appear as visible ones are dismissed
  - [ ] Dismissing a toast records acknowledgment and reveals the next queued notification (if any)
  - [ ] Toasts stack vertically with 10px gap; no overlap or obscuring of each other

#### Feature 5: Per-User Acknowledgment Tracking
- **User Story:** As a BuyerKiosk administrator, I want to see exactly which users have acknowledged each alert so that I can confirm critical messages have been received.
- **Acceptance Criteria:**
  - [ ] Each alert dismissal records the user ID and timestamp
  - [ ] Once a user dismisses the current version of an alert, it does not reappear for that user (across page loads and sessions)
  - [ ] When an admin edits an alert, all acknowledgment records for that alert are deleted — the edited alert is treated as a new version and reappears for all users (this is the one exception to the "never reappear" rule)
  - [ ] The admin dashboard shows per-alert acknowledgment stats: total targeted users, number acknowledged, number pending
  - [ ] Admin can drill into an alert to see the full list of users who have/haven't acknowledged, with timestamps

#### Feature 6: Alert Lifecycle Management
- **User Story:** As a BuyerKiosk administrator, I want to manage alert lifecycle (edit, deactivate, expire) so that I maintain control over what users see.
- **Acceptance Criteria:**
  - [ ] Admin can edit an existing alert's content, severity, display type, targeting, CTA, and expiry
  - [ ] Editing resets all acknowledgments and re-broadcasts the alert via Ably
  - [ ] Admin can immediately deactivate an alert, which hides it for all users regardless of acknowledgment status
  - [ ] Alerts with an expiry date automatically stop displaying after the expiry time passes
  - [ ] Deactivated and expired alerts remain in the management list with their status indicated
  - [ ] Admin can view a history of all alerts (active, expired, deactivated) with filtering

#### Feature 7: Notification Bell with History
- **User Story:** As a store staff member, I want to access a notification bell in the navbar so that I can review current and past alerts at any time.
- **Acceptance Criteria:**
  - [ ] A bell icon appears in the top navigation bar for all users (including admins)
  - [ ] The bell shows an unread count badge when there are unacknowledged system alerts (chat toasts do not count toward unread)
  - [ ] Clicking the bell opens a dropdown showing pending (unacknowledged) alerts at the top and recently dismissed alerts below
  - [ ] Each alert in the dropdown shows title, severity indicator, and timestamp
  - [ ] Clicking a pending alert in the dropdown expands it inline to show the full message; a separate "Dismiss" button marks it as acknowledged
  - [ ] Clicking a CTA link within an expanded alert opens the link and also marks the alert as acknowledged
  - [ ] The unread count updates in realtime as new alerts arrive or are acknowledged

#### Feature 8: Unified Toast Framework (Chat Migration)
- **User Story:** As a developer, I want the chat notification toasts to use the same rendering framework as system alert toasts so that the codebase has one consistent toast system.
- **Acceptance Criteria:**
  - [ ] Chat notifications render through the unified toast component with a "Chat" type (distinct color/icon from Info/Warning/Critical)
  - [ ] All existing chat toast behaviors are preserved: click-to-open-thread, multi-message consolidation (3+ messages in 5 seconds), orphan message handling, notification sound chime
  - [ ] Chat toasts do NOT record database acknowledgments (ephemeral dismiss only)
  - [ ] Chat toasts participate in the max-3-visible queue alongside system alert toasts
  - [ ] Browser notification behavior for chat messages when tab is hidden is preserved
  - [ ] No regression in chat notification functionality after migration — verified by: (a) click-to-open-thread works, (b) consolidation groups 3+ messages in 5s, (c) orphan toasts show phone number, (d) sound chime plays, (e) browser notification fires when tab hidden

### Should Have Features

#### Feature 9: Alert Management Dashboard
- **User Story:** As a BuyerKiosk administrator, I want a comprehensive dashboard to manage all alerts so that I have full visibility and control.
- **Acceptance Criteria:**
  - [ ] Dashboard shows a list/table of all alerts with columns: title, severity, display type, status (active/expired/deactivated), targeting, acknowledgment progress, created date
  - [ ] Sortable and filterable by status, severity, date range, and target stores
  - [ ] Quick actions: edit, deactivate, view acknowledgments from the list
  - [ ] Summary stats at top: total active alerts, total unacknowledged across all alerts

### Could Have Features

#### Feature 10: Alert Sound Notification
- **User Story:** As a store staff member, I want to hear a notification sound for Critical alerts so that I notice them even if I'm not looking at the screen.
- **Acceptance Criteria:**
  - [ ] Critical-severity alerts play an audio chime when they arrive
  - [ ] Sound can be toggled on/off per user (respects existing sound preference patterns)

#### Feature 11: Alert Pinning
- **User Story:** As a BuyerKiosk administrator, I want to pin an alert so that it stays visible and cannot be dismissed until I unpin it.
- **Acceptance Criteria:**
  - [ ] Pinned alerts cannot be closed by staff — no dismiss button
  - [ ] Only admins can unpin (which then allows dismissal)
  - [ ] Pinned alerts always display in the first banner/toast slot

### Won't Have (This Phase)

- **Scheduled alerts** — All alerts publish immediately. Future phase may add scheduling.
- **Per-user targeting** — Alerts target all users or by store, not individual users.
- **Role-based targeting** — Cannot target by user role (e.g., only managers). Future enhancement.
- **Alert templates** — No reusable alert templates or categories. Each alert is composed fresh.
- **Email/SMS fallback** — Alerts are in-app only. No email or SMS delivery.
- **Read receipts / "viewed" state** — There is no intermediate "viewed" state. Acknowledgment means "user clicked dismiss/close." There is no tracking of whether the alert was merely rendered on screen without interaction.
- **Alert threading/replies** — Alerts are one-way communication. No response mechanism.
- **Mobile app push notifications** — In-app only for this phase. Mobile push is a future enhancement.

## Detailed Feature Specifications

### Feature: Unified Toast & Banner Rendering with Queue System

**Description:** A single notification rendering engine handles all in-app notifications — system alert banners, system alert toasts, and chat toasts. It manages a priority queue with a maximum of 3 visible items at any time, automatically revealing queued items as visible ones are dismissed.

**User Flow:**
1. User loads a page (admin or workbook)
2. System checks for unacknowledged alerts from the database targeting this user's store(s)
3. Up to 3 alerts render (banners at page top, toasts in corner) ordered by severity (Critical first) then creation date
4. If more than 3 are pending, the rest are queued invisibly
5. User dismisses an alert → acknowledgment is recorded → next queued alert animates in
6. While on page, new alerts arrive via Ably → added to visible slots (if under 3) or to the queue
7. Chat messages arrive via existing Ably channels → rendered as "Chat" type toasts through the same queue

**Business Rules:**
- Rule 1: Critical alerts always display before Warning, which display before Info. Within the same severity, newer alerts display first.
- Rule 2: A maximum of 3 notifications are visible at any time across both banners and toasts combined.
- Rule 3: An alert with an expiry date that has passed is treated as deactivated — it is not shown to users who haven't seen it and is removed from the queue.
- Rule 4: Editing an alert deletes all acknowledgment records for that alert, causing it to reappear for all users.
- Rule 5: Deactivating an alert immediately removes it from all users' views (via Ably broadcast) regardless of acknowledgment status.
- Rule 6: Chat-type toasts bypass the acknowledgment system entirely — they are ephemeral and never persisted as "alerts."
- Rule 7: Users assigned to multiple stores see alerts targeted to ANY of their assigned stores, but each alert is shown only once regardless of how many of their stores it targets.
- Rule 8: Global alerts (all stores) are seen by every user regardless of store assignment.
- Rule 9: The notification bell unread count reflects only system alerts (not chat toasts).

**Edge Cases:**
- Scenario 1: User is assigned to 3 stores, and an alert targets 2 of them → Expected: User sees the alert once. Acknowledging it covers all targeted stores.
- Scenario 2: Admin edits an alert while a user is viewing it as a banner → Expected: The banner updates in realtime with new content. Previous acknowledgment records are deleted — if user already dismissed it, the edited version reappears as a new alert.
- Scenario 3: Admin deactivates an alert while a user has it queued (not yet visible) → Expected: Alert is silently removed from the queue via Ably `alert:deactivated` event. Next queued alert moves up.
- Scenario 4: User has 5 pending alerts (3 visible, 2 queued) and a new Critical alert arrives → Expected: Critical alert goes to the front of the queue. It does NOT replace a visible notification — it becomes next-to-show when a slot opens.
- Scenario 5: Ably connection drops while user is on page → Expected: Page continues to function. On reconnect, any alerts published during disconnect are fetched via API and displayed. If Ably never reconnects, alerts appear on next page load.
- Scenario 6: Alert expires while visible to a user → Expected: Alert remains visible until the user dismisses it (expiry prevents NEW displays, doesn't remove already-rendered alerts).
- Scenario 7: Two admins edit the same alert simultaneously → Expected: Last write wins. Both edits reset acknowledgments.
- Scenario 8: 3 system alert toasts and a chat message arrive simultaneously → Expected: The 3 system toasts fill visible slots. Chat toast is queued. When a system toast is dismissed, the chat toast appears.
- Scenario 9: User has multiple browser tabs open → Expected: Acknowledging an alert in one tab removes it from all other tabs via Ably self-notification or shared storage. No duplicate toasts across tabs — deduplication by alert ID.
- Scenario 10: User's store assignment changes while they have pending alerts → Expected: On next page load, pending alerts are recalculated from current store assignments. Mid-session, no change — alerts already rendered stay visible.
- Scenario 11: User acknowledges an alert from the bell dropdown while it is also visible as a banner/toast → Expected: The visible banner/toast is also removed. Single acknowledgment covers both.

## Success Metrics

### Key Performance Indicators

- **Adoption:** 80%+ of active BuyerKiosk admins (users with `uri_bkadmin` who logged in during the period) create at least one alert within the first 30 days of launch.
- **Delivery:** 95%+ of targeted users trigger an `alert.delivered` event (via Ably realtime or page-load fallback) within 24 hours of alert publication.
- **Acknowledgment Rate:** 90%+ of targeted users trigger an `alert.acknowledged` event for Critical alerts within 4 hours of their `alert.delivered` event.
- **Engagement:** Median `timeToAcknowledgeSeconds` (from `alert.delivered` to `alert.acknowledged`) is under 2 minutes for Critical, under 24 hours for Info.
- **Quality:** Ably delivery success rate (alerts where `deliveryMethod=ably` / total deliveries) exceeds 90%. Page-load fallback catches the remainder — every published alert eventually reaches every targeted user.

### Tracking Requirements

| Event | Properties | Purpose |
|-------|------------|---------|
| `alert.created` | alertId, severity, displayType, targeting, hasExpiry, hasCTA, createdByUserId | Track alert creation patterns and admin usage |
| `alert.published` | alertId, targetedStoreCount, targetedUserCount | Measure reach of each alert |
| `alert.delivered` | alertId, userId, deliveryMethod (ably/pageLoad), latencyMs | Track realtime vs fallback delivery and speed |
| `alert.acknowledged` | alertId, userId, timeToAcknowledgeSeconds, interactionType (dismiss/bellClick) | Measure engagement speed and acknowledgment path |
| `alert.cta_clicked` | alertId, userId, ctaUrl | Track CTA engagement for actionable alerts |
| `alert.edited` | alertId, editedByUserId, fieldsChanged | Track edit frequency and what changes |
| `alert.deactivated` | alertId, deactivatedByUserId, acknowledgedCount, pendingCount | Track lifecycle completion |
| `alert.expired` | alertId, acknowledgedCount, pendingCount | Track auto-expiry effectiveness |
| `bell.opened` | userId, pendingAlertCount | Track notification center usage |
| `toast.rendered` | alertId, userId, type (system/chat), queuePosition | Track rendering and queue behavior |

---

## Constraints and Assumptions

### Constraints
- Must use existing Ably infrastructure (already paid and integrated)
- Must use Syncfusion components where applicable (RichTextEditor for alert body, Grid for management dashboard)
- All database changes must go through the migration system (`userfrosting/conductor`)
- Must work within existing permission framework (`uri_bkadmin` for admin access)
- Alert data stored in central database (`kiosk_buykiosk`), not per-store databases — alerts are a platform-level feature
- Must not degrade page load performance — alert fetch on page load should complete in under 100ms for typical usage (< 10 active alerts)
- Must support existing browser compatibility (Chrome, Safari, Firefox — latest 2 versions)

### Dependencies
- **Ably SDK** — Frontend (`ably.js`) and backend (`ably/ably-php`) already integrated
- **User-Store Assignments** — `kiosk_users.userStoreAssignments` table is source of truth for alert targeting
- **Permission System** — `uri_bkadmin` permission hook must exist in `authorize_group` for admin access control
- **Syncfusion License** — RichTextEditor and Grid components require active Syncfusion EJ2 license (already in use)
- **Chat Notification Module** — `chat-notifications.js` must be refactored to use unified toast framework; depends on stable chat API

### Assumptions
- All target users have Ably connectivity when on the platform (existing infrastructure handles this)
- The existing chat notification toast codebase can be refactored without breaking changes to chat functionality
- Store staff visit admin pages or workbook at least once per shift (for page-load fallback delivery)
- BuyerKiosk admins will not create more than ~10 concurrent active alerts (queue system handles more, but UI is optimized for this range)
- The central database can handle the acknowledgment write volume without performance issues (one write per user per alert dismiss)

## Risks and Mitigations

| Risk | Impact | Likelihood | Mitigation |
|------|--------|------------|------------|
| Ably channel limits exceeded with dedicated alerts channels | High | Low | Monitor channel usage. Fall back to publishing on existing store channels with a namespaced event prefix if needed. |
| Chat toast migration introduces regressions | High | Medium | Comprehensive test coverage of all chat notification behaviors before migration. Feature flag to toggle between old and new toast rendering. |
| Alert fatigue — too many alerts cause users to ignore them | Medium | Medium | Max 3 visible limit. Severity system helps users triage. Admin dashboard shows acknowledgment rates to self-regulate. |
| Rich text content renders differently in banner vs toast | Low | Medium | Constrain rich text options to formatting that renders well in both modes. Preview functionality in creation form. |
| Multiple admins creating conflicting alerts | Low | Low | Alert management dashboard shows all active alerts. No technical conflict, but could create user confusion. |
| Acknowledgment table grows unbounded | Low | Low | Periodic cleanup of acknowledgments for expired/deactivated alerts older than 90 days. |

## Open Questions

All questions resolved during requirements gathering. No open questions remain.

---

## Supporting Research

### Competitive Analysis

In-app notification systems are standard in SaaS platforms. Common patterns include:
- **Slack/Teams:** Toast notifications with sound, bell icon with unread count, notification preferences per channel
- **Shopify Admin:** Banner alerts at top of dashboard for account issues, system status, and announcements
- **Toast.com (Restaurant POS):** Critical system alerts as full-width banners that cannot be dismissed until acknowledged
- **Zendesk:** Notification center with bell icon, categorized by type, historical view

BuyerKiosk's approach combines banner + toast + bell + acknowledgment tracking, which matches or exceeds the notification capabilities of comparable platforms in the retail/POS space.

### User Research

Based on existing platform usage:
- Store staff check admin pages or workbook multiple times per shift (high page-load frequency = reliable fallback delivery)
- Chat notifications are the only existing realtime notification, and staff respond to them quickly (validates the toast interaction pattern)
- No current mechanism for platform-wide communication has been a recurring pain point during feature rollouts and policy changes

### Market Data

In-app messaging and notification systems are considered table-stakes for B2B SaaS platforms. Platforms with in-app alert systems report 3-5x higher read rates compared to email-only communication for operational messages.
