Complete implementation of the production line incident response system (生產線異常即時反應系統) including: Backend (FastAPI): - User authentication with AD integration and session management - Chat room management (create, list, update, members, roles) - Real-time messaging via WebSocket (typing indicators, reactions) - File storage with MinIO (upload, download, image preview) Frontend (React + Vite): - Authentication flow with token management - Room list with filtering, search, and pagination - Real-time chat interface with WebSocket - File upload with drag-and-drop and image preview - Member management and room settings - Breadcrumb navigation - 53 unit tests (Vitest) Specifications: - authentication: AD auth, sessions, JWT tokens - chat-room: rooms, members, templates - realtime-messaging: WebSocket, messages, reactions - file-storage: MinIO integration, file management - frontend-core: React SPA structure 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
126 lines
5.9 KiB
Markdown
126 lines
5.9 KiB
Markdown
# Add File Upload with MinIO
|
|
|
|
## Why
|
|
Production line incident response requires comprehensive evidence collection through images, PDFs, and equipment logs. Currently, the system supports text-based realtime messaging, but lacks the ability to attach critical visual evidence (defect photos, equipment screenshots) and documentation (inspection reports, maintenance logs) to incident rooms.
|
|
|
|
Without file upload capability:
|
|
- Operators cannot share defect images or equipment failure photos directly in incident rooms
|
|
- Engineers must rely on verbal descriptions instead of visual evidence
|
|
- Critical documentation remains scattered across email/LINE instead of centralized
|
|
- AI report generation cannot reference actual evidence files
|
|
|
|
This change implements MinIO-based file storage, enabling users to upload and reference files within incident rooms while maintaining data sovereignty (all files stay on corporate servers at localhost:9000).
|
|
|
|
## What Changes
|
|
This proposal adds a new **file-storage** capability that:
|
|
|
|
1. **Integrates MinIO object storage** for secure, on-premise file persistence
|
|
2. **Adds file upload REST API** with multipart/form-data support
|
|
3. **Extends database schema** to track file metadata (file_id, uploader, room association)
|
|
4. **Integrates with realtime messaging** to broadcast file upload events via WebSocket
|
|
5. **Implements file access control** based on room membership
|
|
6. **Supports file types** critical for production incidents: images (jpg, png), documents (pdf), logs (txt, log)
|
|
|
|
### Dependencies
|
|
- **Requires**: `authentication` (user identity), `chat-room` (room membership validation), `realtime-messaging` (upload event broadcasting)
|
|
- **Enables**: Future AI report generation (needs file references to embed images in .docx)
|
|
|
|
### Spec Deltas
|
|
- **ADDED** `file-storage` spec with 5 requirements covering upload, download, metadata management, access control, and realtime integration
|
|
|
|
### Risks
|
|
- MinIO service must be running at localhost:9000 (deployment dependency)
|
|
- Large file uploads may impact server memory (mitigation: streaming uploads, size limits)
|
|
- File storage costs scale with incident volume (mitigation: retention policies, compression)
|
|
|
|
## Scenarios
|
|
|
|
### Happy Path: Upload Equipment Failure Photo
|
|
1. Operator detects equipment failure on Line 3
|
|
2. Opens incident room chat interface
|
|
3. Clicks "Attach Image" and selects photo from device (2.5MB jpg)
|
|
4. System validates file type and size
|
|
5. Uploads to MinIO at `room-{room_id}/images/{file_id}.jpg`
|
|
6. Creates database record linking file to room
|
|
7. Broadcasts file upload event via WebSocket to all room members
|
|
8. Other members see thumbnail preview in chat
|
|
9. Clicking thumbnail opens full-resolution image in modal
|
|
10. File remains accessible for report generation
|
|
|
|
### Edge Case: Upload During Network Interruption
|
|
1. User uploads 5MB PDF during unstable network connection
|
|
2. Upload stalls at 60% completion
|
|
3. Connection drops before completion
|
|
4. Client detects failure, retries upload with same file hash
|
|
5. Server checks if partial file exists in MinIO
|
|
6. Resumes upload from 60% (if MinIO supports multipart resume) or restarts
|
|
7. Upload completes, WebSocket broadcast sent
|
|
8. User sees success notification
|
|
|
|
### Error Case: Unauthorized File Access
|
|
1. User A is member of Room-123
|
|
2. User B is NOT member of Room-123
|
|
3. User B attempts `GET /api/rooms/123/files/{file_id}`
|
|
4. System validates room membership
|
|
5. Returns 403 Forbidden with error message
|
|
6. File remains inaccessible to User B
|
|
7. Audit log records attempted unauthorized access
|
|
|
|
### Performance Case: Multiple Simultaneous Uploads
|
|
1. During major incident, 5 team members upload files simultaneously
|
|
2. Each uploads 3-5MB images (total ~20MB concurrent)
|
|
3. FastAPI handles uploads with streaming (not loading full files into memory)
|
|
4. MinIO distributes writes across storage nodes
|
|
5. All uploads complete within 10 seconds
|
|
6. WebSocket broadcasts sent for each file
|
|
7. Database records all file metadata
|
|
8. No server memory exhaustion or crashes
|
|
|
|
## Technical Considerations
|
|
|
|
### MinIO Integration
|
|
- Use `minio` Python SDK (https://min.io/docs/minio/linux/developers/python/minio-py.html)
|
|
- Connection endpoint: `localhost:9000`
|
|
- Bucket naming: `task-reporter-files` (single bucket for all rooms)
|
|
- Object path pattern: `room-{room_id}/{file_type}/{file_id}.{ext}`
|
|
- Authentication: MinIO access key + secret key from environment variables
|
|
|
|
### File Size and Type Limits
|
|
- **Images**: jpg, jpeg, png, gif | Max 10MB per file
|
|
- **Documents**: pdf | Max 20MB per file
|
|
- **Logs**: txt, log, csv | Max 5MB per file
|
|
- Total uploads per room: No limit (subject to storage capacity)
|
|
- MIME type validation using `python-magic` library
|
|
|
|
### Database Schema Extension
|
|
```sql
|
|
CREATE TABLE room_files (
|
|
file_id VARCHAR(36) PRIMARY KEY,
|
|
room_id VARCHAR(36) NOT NULL REFERENCES incident_rooms(room_id),
|
|
uploader_id VARCHAR(255) NOT NULL,
|
|
filename VARCHAR(255) NOT NULL,
|
|
file_type VARCHAR(20) NOT NULL, -- 'image', 'document', 'log'
|
|
mime_type VARCHAR(100) NOT NULL,
|
|
file_size BIGINT NOT NULL, -- bytes
|
|
minio_bucket VARCHAR(100) NOT NULL,
|
|
minio_object_path VARCHAR(500) NOT NULL,
|
|
uploaded_at TIMESTAMP DEFAULT NOW(),
|
|
deleted_at TIMESTAMP, -- soft delete
|
|
INDEX idx_room_files (room_id, uploaded_at DESC),
|
|
INDEX idx_file_uploader (uploader_id)
|
|
);
|
|
```
|
|
|
|
### Security Considerations
|
|
- **Access control**: Validate user is room member before upload/download
|
|
- **File type whitelist**: Reject executables, scripts, or unknown MIME types
|
|
- **Virus scanning**: (Future) integrate ClamAV for uploaded files
|
|
- **Presigned URLs**: Generate time-limited download URLs (expires in 1 hour)
|
|
- **CORS**: Restrict file upload endpoints to internal network only
|
|
|
|
### Performance Requirements
|
|
- File upload latency < 2s for 5MB files on local network
|
|
- Download presigned URL generation < 50ms
|
|
- Support 10 concurrent uploads without degradation
|
|
- File list query < 100ms for rooms with 100+ files
|