Up to 1.1.x the browser drove course generation one request per step and kept the courses, the provider keys and the model settings itself. Closing the tab stopped a course halfway, every browser had to be set up on its own, a deployment could offer providers but not fix which models its users get, and the headless API ran a separate pipeline that drifted from the web app. 1.2.0 moves all of this to the server: courses and media, identity, model configuration and course generation live there, and the browser is a client. Classrooms can now also leave OpenMAIC: as a PPTX that keeps every scene, or as one offline HTML file that plays the lesson.
The cost is the deployment shape: 1.2.0 needs PostgreSQL and a long-running Node.js server. Serverless hosts, Vercel included, stay on 1.1.x. Read Breaking changes and Before you upgrade first, then follow the deployment guide's Upgrading from 1.1.x.
Design: RFC #1754 (release), #1701 (model configuration) and #1809 (classroom export).
Highlights
- Generation runs on the server. Classic generation is a server-side run that keeps going when the page is closed, resumes from its last checkpoint after a restart or a crashed worker, streams progress to every open tab, and pauses at a failed step so that Retry re-runs only that step. Images and videos are generated alongside the scenes, and a single failed item can be retried. The web app and the headless API share one pipeline. #1756 #1759 #1761
- Models are configured on the server.
openmaic.ymldeclares providers and capability slots (llmwithcourse.*,classroomandagent, plustts,asr,image,video,webSearchanddocument).slotsare defaults users may change,lockfixes slots for everyone, andallowUserKeys: falsekeeps users from adding their own providers. Settings take the matching shape (set it up yourself, choose a model or configured by the administrator), and keys are stored encrypted on the server and never leave it. #1727 #1733 #1767 #1793 - Materials are parsed as soon as they are attached. The composer uploads and parses each file in place and shows progress, Ready, or Failed with Retry; Generate waits until every file is ready, and the preview opens without a material-analysis step. #1796
- Identity and persistence. Three identity modes: single-user for personal installations (the Docker Compose default), anonymous visitors (the cookie now lasts 400 days and is renewed while in use), and accounts through host auth methods. Anonymous work can be claimed into an account with
POST /api/identity/claim. Courses, media, custom agents and model settings are stored on the server, the database schema is versioned, and the first load after the upgrade moves each browser's data to the server once. #1757 #1758 - Classroom export.
- The PPTX keeps the whole lesson. Interactive, quiz and PBL scenes stay in place as placeholder slides with an Open online button and a QR code that open the scene in the online classroom. Export PPTX and Export Resource Pack offer placeholder slides (recommended) or slides only. #1811 #1819 #1823 #1693
- Offline HTML. One self-contained file that plays the classroom without a network connection: narration with captions, spotlight and laser, auto-advancing slides, slide video, discussion cards and interactive widget actions; quiz, interactive and PBL scenes hold until the learner moves on. Export with narration and video or without narration. Classrooms over 400 MB are exported as a ZIP of
classroom.htmland its media folders. #1813 #1842 #1845 #1848 #1850
- Inline math survives saving. Formulas typed in the slide text editor are stored as LaTeX source and typeset by the clients, render-service previews and the PPTX export follow, and every KaTeX/Temml path disables formula-defined macros. #1829 #1904 #1827
Security
1.2.0 includes every fix of the 1.1.x security releases, and these advisories:
- GHSA-r2xp-m5r2-g7xj (High): callers could use server-managed provider credentials with arbitrary models. Model authorization is now enforced for server-managed providers across chat, media, speech, model-based web search and workspace assignments. Reported by @13ob0. #1879
- GHSA-x3gm-gw9m-94h9 (Medium): MP4 render jobs were not bound to the requesting owner. Reported by @Duang777. #1884
- GHSA-6jrw-cp5x-j8jc (Low): deleted courses did not revoke legacy classroom media URLs. Reported by @Duang777. #1883
- GHSA-6c52-8h4v-5xvg (High): stored XSS in slides loaded through
/api/persistence. Fixed in 1.1.3 and in this line since 1.2.0-rc.1. #1799
Hardening since rc.2: user-authored skill content is fenced with an unforgeable end marker #1816, formula-defined macros are disabled in every math renderer #1827, and CSS escapes are refused in inline styles #1815.
Breaking changes
- PostgreSQL and a long-running server are required.
DATABASE_URLis mandatory. Deploy with Docker (docker compose upnow includes PostgreSQL and runs single-user on127.0.0.1) or withpnpm start.NEXT_PUBLIC_PERSISTENCEandvercel.jsonare removed. MODEL_ROUTESwithoutopenmaic.ymlstops the server at startup. Deployments running the Pro agent must writeopenmaic.ymlfirst; the route-to-slot table is under "Migrating from the legacy configuration" in the configuration docs. Withoutopenmaic.yml, the provider variables,server-providers.yml,DEFAULT_MODELandMODEL_FALLBACKkeep working but are deprecated.- Providers with server-managed credentials need an explicit model list (
*_MODELS, ormodelsunder the provider inopenmaic.yml/server-providers.yml). Without one, only default, fallback and slot references are authorized. A startup warning names each provider that has credentials but no list. - Upgrade the render-service together with or before the app. Render jobs are owner-bound, and old/new mixes fail closed.
- The browser no longer sends provider settings. The
x-api-key,x-model,x-base-url,x-model-routes,x-image-*andx-video-*headers and the matching body fields are deprecated, honoured only for a slot with nothing assigned and never underallowUserKeys: false. - Headless API.
POST /api/generate-classroomtakes{ requirement, materialIds? }; upload documents first withPOST /api/materials(pdfContentis refused). Job ids are run ids, so earlier job ids answer404. Every capability the server configures runs (GET /api/generate-classroom/capabilitiesreports which). In anonymous-cookie mode, keep one cookie jar for the upload, the submission and the polls. - Routes removed:
/api/generate/{scene-outlines-stream,agent-profiles,scene-content,scene-actions},/api/extract-document,/api/web-search, andGET/POST /api/classroom. Use/api/generation-runs. - A course is read-only while it is being generated (
409 COURSE_GENERATINGfor other writers). - Runtime sessions are keyed by the resolved owner.
PERSISTENCE_DEV_TOKEN,NEXT_PUBLIC_PERSISTENCE_TOKENandPERSISTENCE_ALLOW_INSECURE_DEV_AUTHare removed. If the token was your only access gate, put the deployment behindACCESS_CODE, a gateway or owner auth methods first. - Assets belong to an owner;
ASSET_QUOTA_BYTESis a per-owner limit. - Pi classroom chat refuses models that cannot call tools (
tool_calling_required) and Google's OpenAI-compatible Gemini endpoint (gemini_native_required); use the nativegooglepreset for Gemini. #1894 #1897 - Embedders:
@openmaic/storage0.32–0.37 moves document ownership to thedocumentOwnershiprelation, drops the IndexedDB fallback of the browser storage seams, and removesServerPersistenceProvider.documentStore.
Before you upgrade
- Back up the database. The first start runs the schema migrations; on a large
document_stagestable it builds an index under a write lock, which you can build concurrently beforehand (see the changelog). - Rolling back to 1.1.x needs the ownership copy-back SQL in the changelog, or that backup.
- Set
OPENMAIC_SECRET_KEYwhen several replicas share the database, whendata/does not survive a restart, or when the working directory is read-only. Otherwise back updata/instance-secret.keywith the database. - Choose an identity mode before the first start: single-user, a shared team owner, anonymous, or host auth. Classrooms 1.1.x saved under
data/classroomsare imported once, for the owner configured at that start, so keepdata/. - List the models each provider with server-managed credentials should offer.
- Check which capabilities will run. With the legacy configuration, the first configured provider of each kind becomes the server default; to turn one off for everybody, set its slot to
nulland list it inlock. - Connect PostgreSQL directly or through a session pool. Transaction-mode poolers (PgBouncer
pool_mode = transaction) are not supported. - Follow the guide: Upgrading from 1.1.x lists every step per deployment type.
Also in 1.2.0
- GLM (Zhipu CogView) image generation provider #1832; a notice beside user-entered API keys that they are sent to the server hosting the instance #1158; host hooks for server-side generation runs #1807.
- A long-running server no longer slows down with every request served #1871; exhausted provider plans are explained and not retried #1831 #1861; oversized vision images are re-encoded instead of failing a step #1902; S3-compatible stores with path-style addressing (
AWS_S3_FORCE_PATH_STYLE) #1849. - Packages:
@openmaic/renderer0.1.14,@openmaic/editor0.0.11,@openmaic/generation0.3.20,@openmaic/dsl0.11.3,@openmaic/importer0.3.1,@openmaic/storage0.37.3.
Known issues
- On iPhone, an exported HTML file does not play inside WeChat or the Files preview; open it in Safari or another browser. #1847
- Long formulas in an exported PPTX may wrap onto several lines in PowerPoint and WPS. #1905
- With the renderer-based editor off, the legacy canvas editor flattens inline formulas in a text box when its text is edited. #1868
- Web-search services in Settings → Model Services have no Test connection button, and a token plan connected with an invalid key shows as connected until a course is generated.
Contributors
Thanks to the community contributors and security reporters in this release: @13ob0, @BeAIcoder, @Cham1229, @Duang777, @Ethereal49, @Frank-zhu2000, @Hahaa909, @HEOJUNFO, @jackefn, @mediasambb, @MengMa-dev, @mvanhorn, @nqthiep, @Oliveryfaso, @Tiyatrotist, @UOYABAYOU, @VenusHui, @weinaike, @Yi-111-a, @yipwingtim, @YizukiAme.
Full changelog: CHANGELOG.md · v1.1.0...v1.2.0