# How OpenMAIC Handles Session Materials: Upload Policies and Scheduling Explained

> Learn how OpenMAIC handles session materials with its upload policies and scheduling. Discover file validation, capacity limits, and concurrency control for secure uploads.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: how-to-guide
- Published: 2026-09-13

---

**OpenMAIC splits session materials handling into two distinct layers: a policy layer that validates file types and MIME formats before upload starts, and a scheduling layer that manages capacity limits, concurrency constraints, and HttpOnly cookie establishment during the upload process.**

OpenMAIC's workbench allows educators to attach PDFs, slides, images, and audio/video files to classroom sessions through a robust session materials handling system. This implementation combines strict upload policies with intelligent scheduling mechanisms to ensure security, performance, and resource limits are respected. The architecture separates validation concerns from execution logistics, with core logic residing in [`lib/workbench/material-upload-policy.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/material-upload-policy.ts) and [`lib/workbench/material-upload-scheduling.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/material-upload-scheduling.ts).

## Upload Policy Validation

The policy layer enforces file type restrictions before any network request initiates. It normalizes MIME aliases and constructs accept strings for file inputs while performing runtime validation.

### Allowed File Types and MIME Normalization

OpenMAIC maintains two primary constants defining permissible content: `MEDIA_MIME_TYPES` and `WORKBENCH_MATERIAL_MIME_TYPES`. These arrays include standard formats such as PDF, PPTX, DOCX, PNG, JPEG, and MP4.

To handle vendor-specific MIME aliases (for example, `audio/x-m4a`), the system uses a `MIME_ALIASES` map. The `normalizeWorkbenchMaterialMime` function translates these aliases to canonical forms like `audio/mp4`. This normalization ensures consistent validation across different browsers and operating systems.

The `WORKBENCH_MATERIAL_ACCEPT` constant combines file extensions and MIME types into a comma-separated string used by the `<input type="file">` element's `accept` attribute.

### Runtime File Validation

During file selection, `isWorkbenchMaterialMime(mime)` performs O(1) lookups against a `Set` of normalized MIME types. This runtime check in [`lib/workbench/material-upload-policy.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/material-upload-policy.ts) immediately rejects unsupported files before they reach the scheduling queue.

```typescript
import {
  WORKBENCH_MATERIAL_ACCEPT,
  isWorkbenchMaterialMime,
} from '@/lib/workbench/material-upload-policy';

// Assume `file` comes from an <input> element
if (!WORKBENCH_MATERIAL_ACCEPT.split(',').includes(file.type) &&
    !isWorkbenchMaterialMime(file.type)) {
  throw new Error('Unsupported file type');
}

```

## Upload Scheduling and Capacity Management

Once files pass policy validation, the scheduling layer manages resource allocation, concurrency limits, and authentication state.

### Material Slot Ledger and Capacity Limits

OpenMAIC enforces a hard cap of **20 materials per session** via `MAX_COMPOSER_MATERIALS`. The `MaterialSlotLedger` class tracks occupied slots, pending uploads, and provides transactional helpers: `reserve`, `settle`, `removeCompleted`, and `clearCompleted`.

The `canAcceptMaterialFiles(occupied, selected)` function calculates whether adding new files would exceed the limit. Before queuing uploads, you must reserve slots:

```typescript
import { MaterialSlotLedger, canAcceptMaterialFiles } from '@/lib/workbench/material-upload-scheduling';

const ledger = new MaterialSlotLedger(/* currently occupied slots */);
const newFilesCount = files.length;

if (!ledger.canAccept(newFilesCount)) {
  throw new Error('Too many materials – limit is 20');
}
ledger.reserve(newFilesCount);

```

### Concurrency Control with MaterialUploadQueue

To prevent server overload, `MATERIAL_UPLOAD_CONCURRENCY` limits simultaneous uploads to **3 concurrent requests**. The `MaterialUploadQueue` implements a semaphore-style `run` method that enforces this limit across the upload batch.

### HttpOnly Cookie Authentication Strategy

Because OpenMAIC uses HttpOnly cookies for session ownership, the first successful upload must complete serially to establish the authentication cookie before parallel uploads can proceed. The `uploadFirstSuccessfulThenParallel` function implements this pattern: it processes files one-by-one until the first success, then spawns remaining uploads with the concurrency limit.

The `MaterialUploadIdentityGate` maintains `identityEstablished` state and manages the `MaterialUploadQueue`. When `scheduleMaterialUploadBatch` executes, it checks the gate—if the cookie exists, it runs parallel immediately; otherwise, it waits for the first-successful serial phase.

```typescript
import {
  createMaterialUploadIdentityGate,
  scheduleMaterialUploadBatch,
} from '@/lib/workbench/material-upload-scheduling';

const gate = createMaterialUploadIdentityGate();

async function uploadItem(file: File): Promise<boolean> {
  // Your actual upload implementation – returns true on success
  await someApi.uploadMaterial(file);
  return true;
}

// Fire-and-forget – the function returns a Promise that resolves when all uploads finish
scheduleMaterialUploadBatch(gate, files, uploadItem);

```

## Implementing Session Materials Uploads

### Handling Retry Logic for Transient Failures

For network interruptions or temporary server errors, `retryMaterialUpload` wraps upload attempts with exponential backoff:

```typescript
import { retryMaterialUpload } from '@/lib/workbench/material-upload-scheduling';

await retryMaterialUpload(() => someApi.uploadMaterial(file));

```

### UI Integration Points

The policy and scheduling system integrates into the workbench UI through specific components:

- [`components/workbench/composer-input.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/components/workbench/composer-input.tsx) provides the file picker with `accept={WORKBENCH_MATERIAL_ACCEPT}`
- [`components/workbench/WorkbenchChat.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/components/workbench/WorkbenchChat.tsx) wires the upload utilities into the editor interface

## Summary

- **Policy validation** occurs in [`lib/workbench/material-upload-policy.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/material-upload-policy.ts), defining allowed MIME types, normalizing aliases like `audio/x-m4a` to `audio/mp4`, and providing O(1) runtime checks via `isWorkbenchMaterialMime`.
- **Capacity management** enforces `MAX_COMPOSER_MATERIALS` (20 files maximum) through `MaterialSlotLedger` with `reserve` and `settle` operations.
- **Concurrency limits** of 3 simultaneous uploads are enforced by `MaterialUploadQueue` in [`lib/workbench/material-upload-scheduling.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/material-upload-scheduling.ts).
- **HttpOnly cookie security** requires the `uploadFirstSuccessfulThenParallel` strategy, serializing the first upload to establish authentication before parallelizing remaining files.
- **Batch scheduling** is orchestrated by `scheduleMaterialUploadBatch` and `MaterialUploadIdentityGate`, handling both authenticated and unauthenticated initial states.

## Frequently Asked Questions

### What file types does OpenMAIC support for session materials?

OpenMAIC supports PDFs, PowerPoint (PPTX), Word documents (DOCX), images (PNG, JPEG), and various audio/video formats (MP4, etc.) as defined in `MEDIA_MIME_TYPES` and `WORKBENCH_MATERIAL_MIME_TYPES`. The system normalizes MIME aliases—such as mapping `audio/x-m4a` to `audio/mp4`—to ensure consistent validation across different browsers.

### Why must the first file upload complete successfully before parallel uploads begin?

The first upload must establish an HttpOnly owner cookie for session authentication. Because HttpOnly cookies are inaccessible to JavaScript, the system cannot verify authentication status client-side. The `uploadFirstSuccessfulThenParallel` function ensures the cookie is set by the server response before launching concurrent uploads, preventing authentication failures on parallel requests.

### How many files can users upload simultaneously to an OpenMAIC session?

Users can upload a maximum of **20 materials per session** (`MAX_COMPOSER_MATERIALS`), with **3 concurrent uploads** at any given time (`MATERIAL_UPLOAD_CONCURRENCY`). The `MaterialSlotLedger` prevents exceeding the total capacity, while `MaterialUploadQueue` manages the concurrency semaphore.

### What happens if a user selects more files than the remaining slots allow?

The `canAcceptMaterialFiles` function checks available capacity before any upload begins. If `occupied + selected` exceeds 20, the system rejects the batch immediately with an error, preventing partial uploads or resource over-commitment. The UI typically validates this via `MaterialSlotLedger.canAccept()` before invoking the upload scheduler.