Skip to content

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_ENDPOINT is not set, uses express.static() on /uploads
  • Two buckets: avatars (public-read) and documents (private)

Configuration

VariableDescription
S3_ENDPOINTS3-compatible server URL
S3_ACCESS_KEYAccess key
S3_SECRET_KEYSecret key
S3_PUBLIC_URLPublic URL for file access
S3_BUCKETAvatar bucket
S3_DOCUMENTS_BUCKETDocument bucket

File Validation

Magic bytes

File signature check to prevent extension spoofing:

TypeSignature
JPEGFF D8 FF
PNG89 50 4E 47
GIF47 49 46 38
WebP52 49 46 46 ... 57 45 42 50
PDF25 50 44 46
DOC/DOCXD0 CF 11 E0 / 50 4B 03 04
XLS/XLSXD0 CF 11 E0 / 50 4B 03 04
PPT/PPTXD0 CF 11 E0 / 50 4B 03 04
ZIP50 4B 03 04
MP349 44 33
MP400 00 00 ... 66 74 79 70
WAV52 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