How OpenMAIC Handles Session Materials: Upload Policies and Scheduling Explained
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 and 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 immediately rejects unsupported files before they reach the scheduling queue.
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:
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.
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:
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.tsxprovides the file picker withaccept={WORKBENCH_MATERIAL_ACCEPT}components/workbench/WorkbenchChat.tsxwires the upload utilities into the editor interface
Summary
- Policy validation occurs in
lib/workbench/material-upload-policy.ts, defining allowed MIME types, normalizing aliases likeaudio/x-m4atoaudio/mp4, and providing O(1) runtime checks viaisWorkbenchMaterialMime. - Capacity management enforces
MAX_COMPOSER_MATERIALS(20 files maximum) throughMaterialSlotLedgerwithreserveandsettleoperations. - Concurrency limits of 3 simultaneous uploads are enforced by
MaterialUploadQueueinlib/workbench/material-upload-scheduling.ts. - HttpOnly cookie security requires the
uploadFirstSuccessfulThenParallelstrategy, serializing the first upload to establish authentication before parallelizing remaining files. - Batch scheduling is orchestrated by
scheduleMaterialUploadBatchandMaterialUploadIdentityGate, 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →