Files
egg 44822a561a feat: Improve file display, timezone handling, and LOT management
Changes:
- Fix datetime serialization with UTC 'Z' suffix for correct timezone display
- Add PDF upload support with extension fallback for MIME detection
- Fix LOT add/remove by creating new list for SQLAlchemy JSON change detection
- Add file message components (FileMessage, ImageLightbox, UploadPreview)
- Add multi-file upload support with progress tracking
- Link uploaded files to chat messages via message_id
- Include file attachments in AI report generation
- Update specs for file-storage, realtime-messaging, and ai-report-generation

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

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

17 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, with inline display of file attachments in the chat view.

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 display

  • WHEN a message with message_type=image_ref is rendered in the chat
  • THEN the client SHALL display:
    • A thumbnail of the image (max 300px width)
    • The message content/caption below the image
    • Sender name and timestamp
    • A click-to-expand functionality
  • AND clicking the thumbnail SHALL open a full-size preview lightbox

Scenario: File reference message display

  • WHEN a message with message_type=file_ref is rendered in the chat
  • THEN the client SHALL display:
    • A file type icon (PDF, document, log, etc.)
    • The filename
    • File size in human-readable format
    • A download button/link
    • The message content/caption
    • Sender name and timestamp

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 and all parts of the application.

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

Scenario: File upload timestamp in GMT+8

  • WHEN a file is displayed in chat or file drawer
  • THEN the upload timestamp SHALL be formatted in GMT+8 timezone

Scenario: Report generation timestamp in GMT+8

  • WHEN report metadata is displayed
  • THEN the "generated at" timestamp 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

Requirement: Image Preview Lightbox

The frontend SHALL provide a lightbox component for viewing full-size images from chat messages.

Scenario: Open image lightbox

  • WHEN user clicks on an image thumbnail in the chat
  • THEN a modal overlay SHALL appear
  • AND the full-size image SHALL be displayed centered
  • AND a loading indicator SHALL show while image loads
  • AND the image SHALL be constrained to fit the viewport

Scenario: Close image lightbox

  • WHEN the lightbox is open
  • THEN user can close it by:
    • Clicking the X button
    • Pressing the ESC key
    • Clicking outside the image
  • AND focus SHALL return to the chat

Scenario: Image lightbox with download

  • WHEN the lightbox is open
  • THEN a download button SHALL be visible
  • AND clicking it SHALL download the original file

Requirement: File Type Icons

The frontend SHALL display appropriate icons for different file types in chat messages and file drawer.

Scenario: PDF file icon

  • WHEN a PDF file is displayed
  • THEN a PDF icon (red/document style) SHALL be shown

Scenario: Log/text file icon

  • WHEN a .log or .txt file is displayed
  • THEN a text file icon SHALL be shown

Scenario: Excel file icon

  • WHEN an Excel file (.xlsx, .xls) is displayed
  • THEN a spreadsheet icon (green) SHALL be shown

Scenario: Generic file icon

  • WHEN a file with unknown type is displayed
  • THEN a generic document icon SHALL be shown

Requirement: Upload Preview

The frontend SHALL show a preview of the file being uploaded before the message is sent.

Scenario: Image upload preview

  • WHEN user selects an image file for upload
  • THEN a preview thumbnail SHALL be displayed in the input area
  • AND user can add a caption/description
  • AND user can cancel the upload before sending
  • AND a send button confirms the upload

Scenario: File upload preview

  • WHEN user selects a non-image file for upload
  • THEN file info (name, size, type icon) SHALL be displayed
  • AND user can add a description
  • AND user can cancel or confirm