v0.3.0

Multi-Cloud Object Storage

FacilFlow supports multiple cloud storage providers through a unified abstraction layer, enabling seamless switching between storage backends without code changes.

Supported Providers

Provider Type Use Case
MinIO Self-hosted On-premise deployments, dev/test environments
AWS S3 Cloud AWS-native deployments, high availability
Azure Blob Cloud Azure-native deployments, enterprise integration
Google Cloud Storage Cloud GCP-native deployments, analytics workloads

Architecture Overview

graph TB
    subgraph Frontend["Frontend"]
        UI[Object Store Manager]
        PS[Provider Selector]
        BL[Bucket List]
        OB[Object Browser]
    end

    subgraph Backend["Backend API"]
        PR[/api/storage/providers]
        BR[/api/buckets]
        OR[/api/buckets/:name/objects]
    end

    subgraph Abstraction["Storage Abstraction Layer"]
        IF[StorageProvider Interface]
        FC[StorageProviderFactory]
        RG[StorageProviderRegistry]
    end

    subgraph Providers["Provider Implementations"]
        MP[MinioProvider]
        S3[S3Provider]
        AZ[AzureBlobProvider]
        GC[GCSProvider]
    end

    subgraph Cloud["Cloud Services"]
        MIO[(MinIO)]
        AWS[(AWS S3)]
        AZB[(Azure Blob)]
        GCS[(Google Cloud)]
    end

    UI --> PS
    PS --> PR
    UI --> BL
    BL --> BR
    UI --> OB
    OB --> OR

    PR --> RG
    BR --> RG
    OR --> RG

    RG --> FC
    FC --> IF

    IF --> MP
    IF --> S3
    IF --> AZ
    IF --> GC

    MP --> MIO
    S3 --> AWS
    AZ --> AZB
    GC --> GCS

    style Frontend fill:#0D9488,color:#fff
    style Backend fill:#3B82F6,color:#fff
    style Abstraction fill:#8B5CF6,color:#fff
    style Providers fill:#F59E0B,color:#fff
    style Cloud fill:#1E293B,color:#fff

Storage Provider Interface

All providers implement the StorageProvider interface:

interface StorageProvider {
  readonly type: StorageProviderType
  readonly id: string
  readonly name: string

  // Bucket operations
  listBuckets(): Promise<BucketInfo[]>
  createBucket(name: string, region?: string): Promise<boolean>
  deleteBucket(name: string, force?: boolean): Promise<void>
  bucketExists(name: string): Promise<boolean>

  // Object operations
  listObjects(bucket: string, options?: ListObjectsOptions): Promise<ObjectInfo[]>
  putObject(bucket: string, key: string, data: Buffer | ReadableStream, options?: PutObjectOptions): Promise<PutObjectResult>
  getObject(bucket: string, key: string): Promise<ReadableStream>
  deleteObject(bucket: string, key: string): Promise<void>
  deleteObjects(bucket: string, keys: string[]): Promise<void>
  objectExists(bucket: string, key: string): Promise<boolean>

  // Presigned URLs
  getPresignedUrl(bucket: string, key: string, expiresIn?: number): Promise<string>
  getPresignedPutUrl(bucket: string, key: string, expiresIn?: number): Promise<string>

  // Connection testing
  testConnection(): Promise<ConnectionTestResult>
}

Provider Configuration

Each provider requires specific credentials:

MinIO / AWS S3

{
  "type": "minio",
  "endpoint": "minio.example.com",
  "port": 9000,
  "useSSL": false,
  "credentials": {
    "accessKey": "AKIAIOSFODNN7EXAMPLE",
    "secretKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
  }
}

Azure Blob Storage

{
  "type": "azure-blob",
  "endpoint": "https://account.blob.core.windows.net",
  "credentials": {
    "connectionString": "DefaultEndpointsProtocol=https;AccountName=..."
  }
}

Google Cloud Storage

{
  "type": "gcs",
  "endpoint": "storage.googleapis.com",
  "credentials": {
    "projectId": "my-project-id"
  }
}

:::info GCS Authentication Google Cloud Storage uses Application Default Credentials (ADC). Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to point to your service account key file. :::

API Endpoints

Provider Management

Method Endpoint Description
GET /api/storage/providers List all configured providers
GET /api/storage/providers/types Get supported provider types
GET /api/storage/providers/:id Get provider details (credentials masked)
POST /api/storage/providers Create new provider
PUT /api/storage/providers/:id Update provider config
DELETE /api/storage/providers/:id Delete provider
POST /api/storage/providers/:id/test Test connection

Bucket Operations

Method Endpoint Description
GET /api/buckets List all buckets
POST /api/buckets Create bucket
DELETE /api/buckets/:name Delete bucket

Object Operations

Method Endpoint Description
GET /api/buckets/:name/objects List objects
POST /api/buckets/:name/objects Upload object
DELETE /api/buckets/:name/objects/:key Delete object
POST /api/buckets/:name/objects/delete Batch delete
GET /api/buckets/:name/objects/:key/url Get download URL

Data Flow

sequenceDiagram
    participant U as User
    participant UI as Frontend
    participant API as Backend API
    participant Reg as Registry
    participant Prov as Provider
    participant Cloud as Cloud Storage

    U->>UI: Upload file
    UI->>API: POST /buckets/:name/objects
    API->>Reg: getProvider(id)
    Reg-->>API: Provider instance
    API->>Prov: putObject(bucket, key, data)
    Prov->>Cloud: Upload via SDK
    Cloud-->>Prov: ETag, VersionId
    Prov-->>API: PutObjectResult
    API-->>UI: 201 Created
    UI-->>U: Success notification

Security Considerations

Credential Storage

  • Credentials are stored in-memory (production should use encrypted database)
  • API responses mask sensitive credential values
  • Connection strings and secret keys are never returned in full

Access Control

  • Provider management requires Admin role
  • Bucket operations respect RBAC permissions
  • Presigned URLs have configurable expiration (default: 1 hour)

Frontend Components

ProviderSelector

Dropdown component for selecting active storage provider:

  • Lists all configured providers with type icons
  • “Add Provider” option opens configuration dialog
  • Connection test button with status indicator
  • Provider type badge (MinIO, S3, Azure, GCS)

Object Store Manager Page

Full-featured storage management interface:

  • Provider selector in header
  • Bucket list sidebar
  • Object browser with folder navigation
  • Upload dialog with drag-and-drop
  • Batch operations (select, delete multiple)

Environment Variables

Backend

# Default MinIO provider (auto-registered on startup)
MINIO_ENDPOINT=localhost
MINIO_PORT=9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin
MINIO_USE_SSL=false

Testing

The storage providers have comprehensive test coverage:

Component Tests
StorageProvider interface 26
MinioProvider 28
S3Provider 23
AzureBlobProvider 20
GCSProvider 21
Storage Providers API 17
Total 135

Run tests:

cd backend
npm test -- src/__tests__/services/providers/
npm test -- src/__tests__/routes/storage-providers.test.ts
esc