Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt

Use this file to discover all available pages before exploring further.

Created: 2025-12-22
Status: 📋 Recommendations
Related Specs: PF-10 (Notifications System), PF-36 (System Health Dashboard)

Executive Summary

Recommendations for push notification infrastructure and inbox/notification UI. The stack already covers in-app notifications, realtime updates, and basic push subscriptions; the items below target production readiness and UX gaps.

Current State Assessment

✅ What’s Working Well

  1. Core Infrastructure:
    • Multi-channel notification system (in-app, email, SMS, push)
    • Real-time notification updates via Supabase subscriptions
    • Notification preferences per type and channel
    • Template system with variable substitution
    • Delivery tracking (pending, sent, delivered, read, failed)
    • RLS policies for multi-tenant isolation
  2. UI Components:
    • NotificationCenter dropdown with unread count badge
    • NotificationsPage with filtering, search, and bulk actions
    • NotificationItem with read/unread states
    • Category-based filtering (forms, tasks, automation, compliance, risk, system)
    • Bulk selection and actions (mark as read, delete)
  3. Push Infrastructure (Partial):
    • Push subscription management (usePushSubscription hook)
    • PushNotificationSettings component
    • Database schema for push subscriptions
    • Edge functions for save/remove subscription

⚠️ Critical Gaps

  1. Push Notifications Not Functional:
    • send-push-notification edge function has TODO for web-push library
    • No service worker push event handler
    • VAPID keys not fully integrated
    • No push notification payload handling
  2. Missing Features:
    • No notification grouping/threading
    • No quick actions from notifications
    • No notification sounds/vibration
    • No priority/urgency levels
    • No notification scheduling
    • Limited mobile optimization
    • No notification badges on app icon
  3. UX Improvements Needed:
    • No notification preview/expand
    • No notification history beyond current list
    • No notification analytics
    • Limited accessibility features
    • No notification delivery retry logic

Priority Recommendations

🔴 P0: Critical for Production

1. Complete Push Notification Implementation

Current Issue: Push notifications are partially implemented but not functional. Recommendations:
  1. Integrate web-push library in edge function:
    // supabase/functions/send-push-notification/index.ts
    import { webpush } from 'https://deno.land/x/webpush@v1.0.0/mod.ts';
    
    // Replace TODO with actual web-push implementation
    const subscription = {
      endpoint: sub.endpoint,
      keys: {
        p256dh: sub.p256dh_key,
        auth: sub.auth_key,
      },
    };
    
    await webpush.sendNotification(subscription, payload, {
      vapidDetails: {
        subject: VAPID_SUBJECT,
        publicKey: VAPID_PUBLIC_KEY,
        privateKey: VAPID_PRIVATE_KEY,
      },
    });
    
  2. Add service worker push event handler:
    // public/sw.js or via VitePWA
    self.addEventListener('push', (event) => {
      const data = event.data?.json() || {};
      const options = {
        body: data.body,
        icon: data.icon || '/icons/icon-192x192.png',
        badge: '/icons/badge-72x72.png',
        tag: data.tag || 'notification',
        data: {
          url: data.action_url || '/',
          notificationId: data.notification_id,
        },
        actions: data.actions || [],
        requireInteraction: data.urgent || false,
      };
      
      event.waitUntil(
        self.registration.showNotification(data.title, options)
      );
    });
    
  3. Add notification click handler:
    self.addEventListener('notificationclick', (event) => {
      event.notification.close();
      
      const url = event.notification.data?.url || '/';
      event.waitUntil(
        clients.matchAll({ type: 'window', includeUncontrolled: true })
          .then((clientList) => {
            // Focus existing window or open new one
            for (const client of clientList) {
              if (client.url === url && 'focus' in client) {
                return client.focus();
              }
            }
            return clients.openWindow(url);
          })
      );
    });
    
  4. Fix multi-tenancy security issue:
    • Change pf_push_subscriptions.endpoint from UNIQUE to UNIQUE (user_id, endpoint)
    • Add UPDATE RLS policy
    • Update upsert to use composite conflict key
Files to Update:
  • supabase/functions/send-push-notification/index.ts
  • supabase/migrations/ (new migration for schema fix)
  • public/sw.js or VitePWA service worker config
  • supabase/functions/save-push-subscription/index.ts
Estimated Effort: 2-3 days

2. Notification Grouping and Threading

Problem: Related notifications (e.g., multiple form submissions) clutter the inbox. Recommendations:
  1. Add grouping logic:
    // Group by type + entity_id + time window (5 minutes)
    interface NotificationGroup {
      id: string;
      type: notification_type;
      entity_id?: string;
      title: string;
      count: number;
      notifications: Notification[];
      latest_at: string;
    }
    
    const groupNotifications = (notifications: Notification[]): NotificationGroup[] => {
      const groups = new Map<string, Notification[]>();
      
      notifications.forEach((notif) => &#123;
        const key = `${notif.type}-${notif.data?.entity_id || 'none'}`;
        const existing = groups.get(key) || [];
        
        // Only group if within 5 minutes of latest
        if (existing.length > 0) &#123;
          const latest = new Date(existing[0].created_at);
          const current = new Date(notif.created_at);
          const diffMinutes = (current.getTime() - latest.getTime()) / 60000;
          
          if (diffMinutes > 5) &#123;
            // Create new group
            groups.set(`${key}-${notif.id}`, [notif]);
            return;
          &#125;
        &#125;
        
        existing.unshift(notif);
        groups.set(key, existing);
      &#125;);
      
      return Array.from(groups.values()).map((group) => (&#123;
        id: group[0].id,
        type: group[0].type,
        entity_id: group[0].data?.entity_id,
        title: group[0].title,
        count: group.length,
        notifications: group,
        latest_at: group[0].created_at,
      &#125;));
    &#125;;
    
  2. Update UI to show grouped notifications:
    • Show count badge on grouped items
    • Expand/collapse to see individual notifications
    • “Mark all as read” for group
Files to Create/Update:
  • src/platform/notifications/utils/notificationGrouping.ts
  • src/platform/notifications/components/NotificationGroup.tsx
  • src/platform/notifications/NotificationItem.tsx (update to support groups)
Estimated Effort: 2 days

3. Notification Quick Actions

Problem: Users must navigate to detail pages to take action on notifications. Recommendations:
  1. Add action buttons to notifications:
    interface NotificationAction &#123;
      label: string;
      action: string; // 'approve', 'reject', 'view', 'dismiss'
      variant?: 'default' | 'destructive' | 'outline';
      icon?: LucideIcon;
    &#125;
    
    // Define actions per notification type
    const notificationActions: Record<notification_type, NotificationAction[]> = &#123;
      approval_request: [
        &#123; label: 'Approve', action: 'approve', icon: CheckCircle &#125;,
        &#123; label: 'Reject', action: 'reject', variant: 'destructive', icon: XCircle &#125;,
        &#123; label: 'View', action: 'view', variant: 'outline' &#125;,
      ],
      form_submitted: [
        &#123; label: 'Review', action: 'view', icon: Eye &#125;,
      ],
      // ... etc
    &#125;;
    
  2. Implement action handlers:
    • Call appropriate API endpoints
    • Update notification status
    • Show loading states
    • Handle errors gracefully
  3. Add action buttons to NotificationItem:
    • Show actions on hover/click
    • Mobile-friendly touch targets (44x44px)
Files to Create/Update:
  • src/platform/notifications/utils/notificationActions.ts
  • src/platform/notifications/hooks/useNotificationActions.ts
  • src/platform/notifications/NotificationItem.tsx
Estimated Effort: 2-3 days

🟠 P1: High Priority Enhancements

4. Notification Priority and Urgency

Recommendations:
  1. Add priority levels to schema:
    ALTER TABLE pf_notifications 
    ADD COLUMN priority TEXT DEFAULT 'normal' 
    CHECK (priority IN ('low', 'normal', 'high', 'urgent'));
    
    ALTER TABLE pf_notification_preferences
    ADD COLUMN priority_filter TEXT[] DEFAULT ARRAY['normal', 'high', 'urgent'];
    
  2. Visual indicators:
    • Urgent: Red border, pulse animation
    • High: Orange border
    • Normal: Default styling
    • Low: Muted styling
  3. Push notification behavior:
    • Urgent: requireInteraction: true, sound, vibration
    • High: Sound, no vibration
    • Normal: Silent (respect quiet hours)
    • Low: Batched delivery
Files to Update:
  • supabase/migrations/ (new migration)
  • src/platform/notifications/NotificationItem.tsx
  • src/platform/notifications/utils/notificationTypes.ts
  • supabase/functions/send-push-notification/index.ts
Estimated Effort: 1-2 days

5. Notification Sounds and Vibration

Recommendations:
  1. Add sound preferences:
    interface SoundPreferences &#123;
      enabled: boolean;
      volume: number; // 0-1
      sound_type: 'default' | 'custom' | 'none';
      custom_sound_url?: string;
    &#125;
    
  2. Implement sound playback:
    const playNotificationSound = (priority: 'normal' | 'high' | 'urgent') => &#123;
      if (!preferences.sound_enabled) return;
      
      const audio = new Audio(
        priority === 'urgent' 
          ? '/sounds/urgent.mp3'
          : '/sounds/notification.mp3'
      );
      audio.volume = preferences.sound_volume;
      audio.play().catch(console.error);
    &#125;;
    
  3. Add vibration API:
    if ('vibrate' in navigator && priority === 'urgent') &#123;
      navigator.vibrate([200, 100, 200]);
    &#125;
    
Files to Create/Update:
  • src/platform/notifications/utils/soundManager.ts
  • src/platform/notifications/NotificationToastProvider.tsx
  • src/platform/notifications/NotificationCenter.tsx
Estimated Effort: 1 day

6. Mobile Optimization

Recommendations:
  1. Bottom sheet for mobile:
    • Replace dropdown with bottom sheet on mobile (<768px)
    • Full-screen notification page on mobile
    • Swipe gestures (swipe right to mark read, left to delete)
  2. Touch targets:
    • Ensure all interactive elements are 44x44px minimum
    • Add haptic feedback on iOS
  3. PWA badge updates:
    // Update app badge with unread count
    if ('setAppBadge' in navigator) &#123;
      navigator.setAppBadge(unreadCount);
    &#125;
    
Files to Update:
  • src/platform/notifications/NotificationCenter.tsx
  • src/platform/notifications/NotificationsPage.tsx
  • src/platform/notifications/NotificationItem.tsx
  • src/platform/notifications/useNotifications.ts
Estimated Effort: 2-3 days

7. Notification Delivery Retry Logic

Recommendations:
  1. Implement exponential backoff:
    const retryNotification = async (
      notificationId: string,
      attempt: number
    ): Promise<boolean> => &#123;
      const maxAttempts = 3;
      const baseDelay = 1000; // 1 second
      
      if (attempt >= maxAttempts) &#123;
        await markAsFailed(notificationId, 'Max retries exceeded');
        return false;
      &#125;
      
      const delay = baseDelay * Math.pow(2, attempt);
      await new Promise(resolve => setTimeout(resolve, delay));
      
      try &#123;
        await sendNotification(notificationId);
        return true;
      &#125; catch (error) &#123;
        return retryNotification(notificationId, attempt + 1);
      &#125;
    &#125;;
    
  2. Add retry queue:
    • Store failed notifications in retry queue
    • Process queue with exponential backoff
    • Mark as permanently failed after max attempts
Files to Create/Update:
  • supabase/functions/send-pending-notifications/index.ts (enhance existing)
  • supabase/migrations/ (add retry tracking columns)
Estimated Effort: 1-2 days

🟡 P2: Nice to Have

8. Notification Analytics

Recommendations:
  1. Track metrics:
    • Delivery rates by channel
    • Read rates by type
    • Time to read
    • Action rates (click-through)
    • Unsubscribe rates
  2. Add analytics table:
    CREATE TABLE pf_notification_analytics (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      notification_id UUID REFERENCES pf_notifications(id),
      event_type TEXT NOT NULL, -- 'sent', 'delivered', 'read', 'clicked', 'dismissed'
      event_at TIMESTAMPTZ NOT NULL DEFAULT now(),
      metadata JSONB DEFAULT '&#123;&#125;'
    );
    
  3. Dashboard view:
    • Show analytics in notification preferences page
    • Charts for delivery/read rates
    • Export to CSV
Files to Create:
  • supabase/migrations/ (analytics table)
  • src/platform/notifications/components/NotificationAnalytics.tsx
  • src/platform/notifications/hooks/useNotificationAnalytics.ts
Estimated Effort: 2-3 days

9. Notification Scheduling

Recommendations:
  1. Add scheduled delivery:
    ALTER TABLE pf_notifications
    ADD COLUMN scheduled_for TIMESTAMPTZ;
    ADD COLUMN timezone TEXT;
    
  2. Respect quiet hours:
    • Delay delivery during quiet hours
    • Batch low-priority notifications
    • Send urgent notifications immediately
  3. Scheduled notification processor:
    • Cron job to check for scheduled notifications
    • Process in batches
    • Handle timezone conversions
Files to Create/Update:
  • supabase/migrations/ (add columns)
  • supabase/functions/process-scheduled-notifications/index.ts
  • src/platform/notifications/utils/scheduling.ts
Estimated Effort: 2 days

10. Notification History and Archive

Recommendations:
  1. Add archive functionality:
    ALTER TABLE pf_notifications
    ADD COLUMN archived_at TIMESTAMPTZ;
    ADD COLUMN archived_by UUID REFERENCES pf_profiles(id);
    
  2. Archive view:
    • Separate tab for archived notifications
    • Auto-archive after 90 days
    • Search archived notifications
  3. Export functionality:
    • Export to CSV
    • Include read/delivery timestamps
    • Filter by date range
Files to Update:
  • supabase/migrations/ (add columns)
  • src/platform/notifications/NotificationsPage.tsx
  • src/platform/notifications/hooks/useNotifications.ts
Estimated Effort: 1-2 days

11. Notification Templates UI

Recommendations:
  1. Template management page:
    • List all templates (platform + org)
    • Create/edit templates
    • Preview with sample data
    • Test template rendering
  2. Template variables:
    • Show available variables per type
    • Variable picker in editor
    • Syntax highlighting for template syntax
Files to Create:
  • src/platform/notifications/NotificationTemplatesPage.tsx
  • src/platform/notifications/components/TemplateEditor.tsx
  • src/platform/notifications/hooks/useNotificationTemplates.ts
Estimated Effort: 3-4 days

12. Enhanced Accessibility

Recommendations:
  1. Screen reader support:
    • Announce new notifications
    • Describe notification content
    • Announce actions taken
  2. Keyboard navigation:
    • Full keyboard support for notification center
    • Keyboard shortcuts (e.g., N for notifications)
    • Focus management
  3. High contrast mode:
    • Support for high contrast themes
    • Color-blind friendly indicators
    • Text alternatives for icons
Files to Update:
  • src/platform/notifications/NotificationCenter.tsx
  • src/platform/notifications/NotificationItem.tsx
  • src/platform/notifications/NotificationsPage.tsx
Estimated Effort: 2 days

Implementation Roadmap

Phase 1: Critical Fixes (Week 1-2)

  • ✅ Complete push notification implementation
  • ✅ Fix multi-tenancy security issue
  • ✅ Add service worker push handlers
  • ✅ Notification grouping
Deliverable: Functional push notifications with security fixes

Phase 2: Core Enhancements (Week 3-4)

  • ✅ Quick actions
  • ✅ Priority/urgency levels
  • ✅ Sounds and vibration
  • ✅ Mobile optimization
Deliverable: Enhanced UX with mobile support

Phase 3: Reliability (Week 5)

  • ✅ Retry logic
  • ✅ Delivery tracking improvements
  • ✅ Error handling
Deliverable: Production-ready reliability

Phase 4: Advanced Features (Week 6-8)

  • ✅ Analytics
  • ✅ Scheduling
  • ✅ Archive/history
  • ✅ Template UI
Deliverable: Complete notification management

Security Considerations

Critical Security Fixes

  1. Push Subscription Multi-Tenancy:
    • Issue: endpoint UNIQUE constraint allows cross-user hijacking
    • Fix: Change to UNIQUE (user_id, endpoint) + UPDATE RLS policy
    • Priority: P0 - Critical
  2. VAPID Key Management:
    • Store keys as Supabase secrets (not in code)
    • Rotate keys periodically
    • Use different keys per environment
  3. Notification Data Validation:
    • Sanitize notification content (prevent XSS)
    • Validate action URLs (prevent open redirect)
    • Rate limit notification creation

Performance Considerations

  1. Real-time Subscription Optimization:
    • Use Supabase filters to reduce payload size
    • Debounce notification updates
    • Batch UI updates
  2. Notification List Virtualization:
    • Use react-window or react-virtuoso for long lists
    • Lazy load notification details
    • Paginate notification history
  3. Push Notification Batching:
    • Batch multiple notifications per user
    • Use notification groups
    • Rate limit push delivery

Testing Recommendations

Unit Tests

  • Notification grouping logic
  • Priority/urgency calculations
  • Sound/vibration preferences
  • Action handlers

Integration Tests

  • Push subscription flow
  • Notification delivery
  • Retry logic
  • Multi-device sync

E2E Tests

  • Complete notification flow (create → deliver → read)
  • Push notification delivery
  • Quick actions
  • Mobile interactions

Metrics and Success Criteria

Key Metrics

  • Push Notification Delivery Rate: >95%
  • Notification Read Rate: >70% within 24 hours
  • Action Rate: >30% (for actionable notifications)
  • User Satisfaction: >4.0/5.0 (survey)

Success Criteria

  • ✅ Push notifications work on all supported browsers
  • ✅ Zero security vulnerabilities
  • ✅ <2s notification delivery latency
  • ✅ Mobile UX matches desktop quality
  • ✅ 99.9% notification delivery reliability

References


Last Updated: 2025-12-22
Next Review: After Phase 1 implementation