Files
Task_Reporter/openspec/specs/realtime-messaging/spec.md
egg 599802b818 feat: Add Chat UX improvements with notifications and @mention support
- Add ActionBar component with expandable toolbar for mobile
- Add @mention functionality with autocomplete dropdown
- Add browser notification system (push, sound, vibration)
- Add NotificationSettings modal for user preferences
- Add mention badges on room list cards
- Add ReportPreview with Markdown rendering and copy/download
- Add message copy functionality with hover actions
- Add backend mentions field to messages with Alembic migration
- Add lots field to rooms, remove templates
- Optimize WebSocket database session handling
- Various UX polish (animations, accessibility)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 08:20:37 +08:00

14 KiB

realtime-messaging Specification

Purpose

TBD - created by archiving change add-realtime-messaging. Update Purpose after archive.

Requirements

Requirement: WebSocket Connection Management

The system SHALL provide WebSocket endpoints for establishing persistent bidirectional connections between clients and server, with automatic reconnection handling and connection state management.

Scenario: Establish WebSocket connection

  • WHEN an authenticated user connects to ws://localhost:8000/ws/{room_id}
  • THEN the system SHALL validate user's room membership
  • AND establish a WebSocket connection
  • AND add the connection to the room's active connections pool
  • AND broadcast a "user joined" event to other room members

Scenario: Handle connection authentication

  • WHEN a WebSocket connection request is made without valid authentication token
  • THEN the system SHALL reject the connection with status 401
  • AND close the WebSocket immediately

Scenario: Automatic reconnection

  • WHEN a WebSocket connection is dropped unexpectedly
  • THEN the client SHALL attempt to reconnect automatically with exponential backoff
  • AND resume from the last received message sequence number
  • AND request any missed messages during disconnection

Requirement: Real-time Message Broadcasting

The system SHALL broadcast messages to all active room members in real-time, ensuring message ordering and delivery acknowledgment.

Scenario: Send text message

  • WHEN a room member sends a message via WebSocket:
    {
      "type": "message",
      "content": "Equipment temperature rising to 85°C",
      "message_type": "text"
    }
    
  • THEN the system SHALL:
    • Validate user has write permission (OWNER or EDITOR role)
    • Assign a unique message_id and timestamp
    • Store the message in database
    • Broadcast to all active WebSocket connections in the room
    • Return acknowledgment to sender with message_id

Scenario: Send system notification

  • WHEN a system event occurs (user joined, room status changed, etc.)
  • THEN the system SHALL broadcast a system message:
    {
      "type": "system",
      "event": "user_joined",
      "user_id": "john.doe@panjit.com.tw",
      "timestamp": "2025-11-17T10:00:00Z"
    }
    
  • AND all connected clients SHALL display the notification

Scenario: Handle message ordering

  • WHEN multiple messages are sent simultaneously
  • THEN the system SHALL ensure FIFO ordering using message sequence numbers
  • AND clients SHALL display messages in the correct order

Requirement: Message Persistence and History

The system SHALL persist all messages to database for audit trail, report generation, and history retrieval.

Scenario: Store message in database

  • WHEN a message is sent through WebSocket
  • THEN the system SHALL create a database record with:
    • message_id (UUID)
    • room_id (FK to incident_rooms)
    • sender_id (user email)
    • content (text or JSON for structured messages)
    • message_type (text, image_ref, file_ref, system)
    • created_at timestamp
    • edited_at (nullable for message edits)
    • deleted_at (nullable for soft delete)
    • sequence_number (for ordering)

Scenario: Retrieve message history

  • WHEN a user joins a room or reconnects
  • THEN the system SHALL load recent messages via GET /api/rooms/{room_id}/messages?limit=50&before={timestamp}
  • AND return messages in reverse chronological order
  • AND include pagination metadata for loading more history

Scenario: Search messages

  • WHEN a user searches for messages containing specific keywords
  • THEN the system SHALL query the database with full-text search
  • AND return matching messages with highlighted search terms
  • AND maintain user's access control (only rooms they're members of)

Requirement: Message Types and Formatting

The system SHALL support various message types including text, image references, file references, and structured data for production incidents.

Scenario: Text message with mentions

  • WHEN a user sends a message with @mentions
    {
      "content": "@maintenance_team Please check Line 3 immediately",
      "mentions": ["maintenance_team@panjit.com.tw"]
    }
    
  • THEN the system SHALL parse and store mentions
  • AND potentially trigger notifications to mentioned users

Scenario: Image reference message

  • WHEN a user uploads an image and sends reference
    {
      "type": "message",
      "message_type": "image_ref",
      "content": "Defect found on product",
      "file_id": "550e8400-e29b-41d4-a716-446655440000",
      "file_url": "http://localhost:9000/bucket/room-123/image.jpg"
    }
    
  • THEN the system SHALL store the file reference
  • AND clients SHALL display image preview inline

Scenario: Structured incident data

  • WHEN reporting specific incident metrics
    {
      "type": "message",
      "message_type": "incident_data",
      "content": {
        "temperature": 85,
        "pressure": 120,
        "production_rate": 450,
        "timestamp": "2025-11-17T10:15:00Z"
      }
    }
    
  • THEN the system SHALL store structured data as JSON
  • AND enable querying/filtering by specific fields later

Requirement: Connection State Management

The system SHALL track online presence and typing indicators for better collaboration experience.

Scenario: Track online users

  • WHEN users connect/disconnect from a room
  • THEN the system SHALL maintain a list of online users
  • AND broadcast presence updates to all room members
  • AND display online status indicators in UI

Scenario: Typing indicators

  • WHEN a user starts typing a message
  • THEN the client SHALL send a "typing" event via WebSocket
  • AND the system SHALL broadcast to other room members
  • AND automatically clear typing status after 3 seconds of inactivity

Scenario: Connection health monitoring

  • WHEN a WebSocket connection is established
  • THEN the system SHALL send ping frames every 30 seconds
  • AND expect pong responses within 10 seconds
  • AND terminate connection if no response received

Requirement: Message Operations

The system SHALL support message editing and deletion with proper audit trail and permissions.

Scenario: Edit own message

  • WHEN a user edits their own message within 15 minutes
    {
      "type": "edit_message",
      "message_id": "msg-123",
      "content": "Updated: Equipment temperature stabilized at 75°C"
    }
    
  • THEN the system SHALL update the message content
  • AND set edited_at timestamp
  • AND broadcast the edit to all connected clients
  • AND preserve original message in audit log

Scenario: Delete message

  • WHEN a user deletes their own message or admin deletes any message
  • THEN the system SHALL perform soft delete (set deleted_at)
  • AND broadcast deletion event to all clients
  • AND clients SHALL show "message deleted" placeholder
  • AND preserve message in database for audit

Scenario: React to message

  • WHEN a user adds a reaction emoji to a message
    {
      "type": "add_reaction",
      "message_id": "msg-123",
      "emoji": "👍"
    }
    
  • THEN the system SHALL store the reaction
  • AND broadcast to all connected clients
  • AND aggregate reaction counts for display

Requirement: Short-lived Database Sessions for WebSocket

The system SHALL process WebSocket messages using short-lived database sessions that are acquired and released for each individual operation, rather than holding a session for the entire WebSocket connection lifetime.

Scenario: Message creation with short session

  • WHEN a user sends a message via WebSocket
  • THEN the system acquires a database session
  • AND creates the message with proper sequence number
  • AND commits the transaction
  • AND releases the session immediately
  • AND broadcasts the message to room members

Scenario: Concurrent message handling

  • WHEN multiple users send messages simultaneously
  • THEN each message operation uses an independent database session
  • AND sequence numbers are correctly assigned without duplicates
  • AND no connection pool exhaustion occurs

Requirement: Message Sequence Number Integrity

The system SHALL guarantee unique, monotonically increasing sequence numbers per room using database-level locking to prevent race conditions during concurrent message creation.

Scenario: Concurrent sequence assignment

  • WHEN two users send messages to the same room at the exact same time
  • THEN each message receives a unique sequence number
  • AND the sequence numbers are consecutive without gaps or duplicates

Scenario: High concurrency sequence safety

  • WHEN 50+ users send messages to the same room simultaneously
  • THEN all messages receive correct unique sequence numbers
  • AND the operation does not cause deadlocks

Requirement: Configurable Database Connection Pool

The system SHALL support environment variable configuration for database connection pool parameters to optimize for different deployment scales.

Scenario: Custom pool size configuration

  • WHEN the application starts with DB_POOL_SIZE=20 environment variable
  • THEN the connection pool maintains 20 persistent connections

Scenario: Pool overflow configuration

  • WHEN the application starts with DB_MAX_OVERFLOW=30 environment variable
  • THEN the connection pool can expand up to 30 additional connections beyond the pool size

Scenario: Pool timeout configuration

  • WHEN all connections are in use and a new request arrives
  • AND DB_POOL_TIMEOUT=10 is configured
  • THEN the request waits up to 10 seconds for an available connection
  • AND raises an error if no connection becomes available

Scenario: Default configuration

  • WHEN no database pool environment variables are set
  • THEN the system uses production-ready defaults (pool_size=20, max_overflow=30, timeout=10, recycle=1800)

Requirement: Message Sender Display Name

The system SHALL include the sender's display name in message responses and broadcasts, enabling the UI to show user-friendly names instead of email addresses.

Scenario: Message response includes display name

  • WHEN a message is retrieved via REST API or WebSocket
  • THEN the response SHALL include sender_display_name field
  • AND the display name SHALL be obtained by joining with the tr_users table
  • AND if the sender does not exist in tr_users, the field SHALL fallback to sender_id

Scenario: WebSocket broadcast includes display name

  • WHEN a new message is broadcast via WebSocket
  • THEN the broadcast SHALL include sender_display_name field
  • AND the value SHALL be the sender's display name from tr_users table

Scenario: Historical messages include display name

  • WHEN a client requests message history via GET /api/rooms/{room_id}/messages
  • THEN each message in the response SHALL include sender_display_name
  • AND messages from unknown users SHALL show their sender_id as fallback

Requirement: GMT+8 Timezone Display

The frontend SHALL display all timestamps in GMT+8 (Asia/Taipei) timezone for consistent user experience across all browsers.

Scenario: Message timestamp in GMT+8

  • WHEN a message is displayed in the chat room
  • THEN the timestamp SHALL be formatted in GMT+8 timezone
  • AND use format "HH:mm" for today's messages
  • AND use format "MM/DD HH:mm" for older messages

Scenario: Room list timestamps in GMT+8

  • WHEN the room list is displayed
  • THEN the "last updated" time SHALL be formatted in GMT+8 timezone

Requirement: @Mention Support

The messaging system SHALL support @mention functionality to tag specific users in messages.

Scenario: Trigger mention autocomplete

  • WHEN user types @ in the message input
  • THEN a dropdown menu appears showing room members
  • AND the list filters as user continues typing
  • AND user can select a member using keyboard or mouse

Scenario: Insert mention into message

  • WHEN user selects a member from the mention dropdown
  • THEN the mention is inserted as @display_name
  • AND the mention is stored with the user_id reference
  • AND the mention is visually highlighted in the message

Scenario: Mention notification

  • WHEN a message containing @mention is sent
  • THEN the mentioned user receives a highlighted notification
  • AND the notification indicates they were mentioned

Requirement: Browser Push Notifications

The system SHALL support browser push notifications for new messages.

Scenario: Request notification permission

  • WHEN user first visits the chat room
  • THEN the system prompts for notification permission
  • AND the permission state is stored locally

Scenario: Send push notification

  • WHEN a new message arrives while the tab is not focused
  • AND user has granted notification permission
  • THEN a browser push notification is displayed
  • AND clicking the notification focuses the chat room

Requirement: Sound and Vibration Alerts

The system SHALL support audio and haptic feedback for new messages.

Scenario: Play notification sound

  • WHEN a new message arrives
  • AND sound notifications are enabled
  • THEN a notification sound is played

Scenario: Vibrate on mobile

  • WHEN a new message arrives on a mobile device
  • AND vibration is enabled
  • AND the device supports Vibration API
  • THEN the device vibrates briefly

Requirement: Mention Data Storage

Messages with @mentions SHALL store the mention metadata for querying.

Scenario: Store mention references

  • WHEN a message with @mentions is created
  • THEN the mentions field stores an array of mentioned user_ids
  • AND the message content preserves the @display_name format

Scenario: Query messages mentioning user

  • WHEN fetching messages that mention a specific user
  • THEN messages with that user_id in mentions array are returned