feat: Initial commit - Task Reporter incident response system
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>
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user