---
title: Architecture
path: introduction/architecture
status: published
---

ScaiDrive is a FastAPI application backed by MariaDB, Redis, and S3. A request enters through middleware, authenticates against ScaiKey, dispatches to a service layer, and mutates database state or streams content from object storage.

## High-level view

```mermaid
flowchart TB
  subgraph Clients["Clients"]
    direction LR
    C1["desktop · mobile · web<br/>CLI · SDK"]
  end

  subgraph Server["ScaiDrive Server (FastAPI / Python)"]
    direction TB
    MW["Middleware<br/>request-id · CORS · audit"]
    AU["Auth (JWT via ScaiKey)"]
    RT["Routers<br/>/api/v1/files · /shares<br/>/sync · /search · …"]
    SV["Services<br/>files · folders · shares<br/>sync · permissions · search"]
    ST["Storage & Indexes"]
    MW --> AU --> RT --> SV --> ST
  end

  C1 -->|HTTPS| MW
  C1 -.->|WebSocket /ws| Server

  DB[("MariaDB<br/>metadata · ACLs<br/>changelog")]
  RD[("Redis<br/>cache · queues<br/>sessions")]
  S3[("S3 / Garage<br/>blobs · chunks")]
  WV[("Weaviate<br/>(optional)<br/>semantic search")]

  ST --> DB
  ST --> RD
  ST --> S3
  RD --> WV
```

## Request flow

For `PATCH /api/v1/files/{file_id}`:

1. **Middleware** assigns a request ID, applies CORS, logs start time.
2. **Authentication** validates the Bearer JWT: fetches the JWKS from ScaiKey (cached five minutes), verifies the RS256/ES256 signature, checks the issuer, decodes the claims (`sub`, `tenant_id`, `email`, `groups`, `scope`).
3. **JIT provisioning** looks up the user in the local DB. If they don't exist yet, a row is inserted. Last-login is updated. Active/suspended status is checked.
4. **Router** dispatches to the file handler.
5. **Permission check** consults the ACL system: does this user have `WRITE` on this file? Considers direct ACEs on the file, inherited ACEs from the parent folder, share membership role, and global admin roles. Allow + deny merged per NTFS semantics.
6. **Service layer** updates the file row, writes a new `ChangeLog` entry (so connected clients see the change), and flushes through.
7. **Event broadcast** publishes the change to the Redis pub/sub channel for that share. Any WebSocket subscribers get a `file_updated` frame.
8. **Response** returns the updated metadata inside the standard envelope.

For file uploads, step 6 is more involved: the file body is streamed to S3 in chunks, SHA-256 hashes are computed per chunk, existing chunks are deduplicated, a `File` row and `FileVersion` row are created, and only then does a `ChangeLog` entry get written.

## Core services

| Service | Responsibility |
|---------|----------------|
| **FileService** | Upload, download, copy, move, delete, version management |
| **FolderService** | Folder CRUD, hierarchical queries, move/rename |
| **ShareService** | Share creation, membership, invitations |
| **PermissionService** | ACL evaluation, effective permissions, inheritance |
| **SyncService** | Cursor tracking, change log, conflict detection, device registry |
| **SearchService** | Keyword search, semantic search, hybrid search, RAG context |
| **VectorizationService** | Chunk files, embed, index in Weaviate |
| **ExternalSharingService** | Public links, guest sessions, link-based uploads |
| **QuotaService** | Multi-level quota enforcement, usage aggregation |
| **SMBConnectorService** | Bidirectional SMB sync, identity mapping |
| **SharePointConnectorService** | Microsoft 365 sync via Graph |
| **AuditService** | Compliance event logging |

## Storage

| Store | Used for |
|-------|----------|
| **MariaDB** | Users, groups, shares, file/folder metadata, ACLs, change log, sync cursors, quotas, audit log, connectors |
| **Redis** | Cache (JWKS, permission results), task queue (ARQ), WebSocket pub/sub, rate-limit counters, real-time state |
| **S3 (Garage, MinIO, AWS S3)** | File content chunks, uploaded blobs |
| **Weaviate** | (Optional) Vector index for semantic search |
| **ScaiKey** | Identity provider — users, groups, OAuth tokens |
| **ScaiSend** | Transactional email — invitation mails, share notifications |

All are external dependencies. ScaiDrive doesn't embed any of them.

## ScaiKey integration

ScaiDrive does not have its own login flow. Authentication is delegated to ScaiKey, a separate OAuth 2.0 / OIDC identity provider. Users log in to ScaiKey and receive a JWT; they present that JWT to ScaiDrive as `Authorization: Bearer <token>`.

**What ScaiKey does:**

- Issues access tokens (JWT, RS256) and refresh tokens.
- Manages the canonical user and group records.
- Publishes webhooks on `user.created`, `user.updated`, `user.deleted`, `group.*` so ScaiDrive stays in sync.
- Exposes JWKS at `/.well-known/jwks.json` for signature verification.

**What ScaiDrive does:**

- Accepts JWTs issued by ScaiKey.
- Provisions users just-in-time on first login (JIT provisioning).
- Receives ScaiKey webhooks and reconciles local user/group state.
- Proxies the OAuth dance for desktop and mobile clients via `/api/v1/auth/config`, `/api/v1/auth/token`.

See [Authentication](/docs/scaidrive/getting-started/authentication).

## Runtime modes

The ScaiDrive server binary runs in one of three modes, selected by environment:

- **`api`** — FastAPI HTTP server (default). Serves `/api/v1/*`, WebSocket endpoints, `/health`.
- **`worker`** — ARQ background worker. Runs vectorization jobs, connector syncs, quota recalculation, retention cleanups.
- **`migrate`** — Runs Alembic migrations, then exits.

Production deployments run all three as separate containers off the same Docker image.

## Clients

Official clients consume the HTTP API:

- **Python SDK** — `sdk-python` package, async and sync clients.
- **JavaScript/TypeScript SDK** — `sdk-js` package.
- **.NET SDK** — `sdk-dotnet` package.
- **Desktop** — PyQt6 app using `client-core` (Windows, macOS, Linux).
- **CLI** — `client-cli` for scripting.
- **Web Admin UI** — SolidJS app under `/admin`.
- **Web Client** — SolidJS app for end users.
- **MCP Server** — exposes ScaiDrive as tools for Claude and other MCP-compatible LLMs. See [MCP Server](/docs/scaidrive/advanced/mcp-server).

All clients hit the same API. The desktop client, mobile apps, and web client use identical endpoints.

## What's next

- [Quickstart](/docs/scaidrive/getting-started/quickstart) — first API call.
- [Authentication](/docs/scaidrive/getting-started/authentication) — the ScaiKey handshake in detail.
- [Sync Model](/docs/scaidrive/core-concepts/sync-model) — how clients stay in sync.