File Storage
Planner uses S3-compatible object storage for files with local filesystem fallback.
Architecture
- S3 client —
@aws-sdk/client-s3(supports MinIO, Regru Cloud, AWS S3) - Local fallback — if
S3_ENDPOINTis not set, usesexpress.static()on/uploads - Two buckets: avatars (public-read) and documents (private)
Configuration
| Variable | Description |
|---|---|
S3_ENDPOINT | S3-compatible server URL |
S3_ACCESS_KEY | Access key |
S3_SECRET_KEY | Secret key |
S3_PUBLIC_URL | Public URL for file access |
S3_BUCKET | Avatar bucket |
S3_DOCUMENTS_BUCKET | Document bucket |
File Validation
Magic bytes
File signature check to prevent extension spoofing:
| Type | Signature |
|---|---|
| JPEG | FF D8 FF |
| PNG | 89 50 4E 47 |
| GIF | 47 49 46 38 |
| WebP | 52 49 46 46 ... 57 45 42 50 |
25 50 44 46 | |
| DOC/DOCX | D0 CF 11 E0 / 50 4B 03 04 |
| XLS/XLSX | D0 CF 11 E0 / 50 4B 03 04 |
| PPT/PPTX | D0 CF 11 E0 / 50 4B 03 04 |
| ZIP | 50 4B 03 04 |
| MP3 | 49 44 33 |
| MP4 | 00 00 00 ... 66 74 79 70 |
| WAV | 52 49 46 46 ... 57 41 56 45 |
Restrictions
- SVG blocked — XSS risk
- Max size: 50MB (documents), 2MB (avatars)
- Content-Disposition: documents served as
attachment - X-Content-Type-Options:
nosniff
Usage
StorageService is an internal service used by modules:
- Users — avatars
- Tasks — task attachments
- Comments — comment attachments
- Chat — message attachments