name: fantasia-electron-main description: >- Works on Fantasia Archive Electron main process: app lifecycle, window management, platform tweaks, native integrations, and ipcMain registration (register*Ipc + electron-ipc-bridge channel names). Use when editing electron-main.ts, src-electron/mainScripts/, or main-side tests.
Fantasia Archive — Electron main process
Entry and flow
- Entry:
electron-main.ts— Chromium stderr filter, app name/userData, Windows DevTools workaround,startApp(all IPC registrars), native shell menu,openAppWindowManager.startApp()before anyBrowserWindowso preload channels exist before renderer load. - IPC style: prefer
ipcMain.handle+ipcRenderer.invoke.sendSynclast resort only — document exceptions. userData:fixAppName()inappIdentity_manager.ts.TEST_ENVcomponents/e2e→playwright-user-dataviaplaywrightIsolatedUserDataDirName.ts- Modules:
src-electron/mainScripts/feature folders over growingelectron-main.ts - IPC registration: channel strings
electron-ipc-bridge.ts; handlersipcManagement/register*Ipc.ts;registerAllFaIpc()fromipcManagement_manager.ts
IPC payload validation (Zod)
ipcMain.handle args untrusted at runtime — validate in main before stores/privileged APIs.
- Objects/patches: Zod schema in
src-electron/shared/— referencefaUserSettingsPatchSchema.ts - Throw on invalid →
invokerejects; renderer handles - Single primitives:
typeof+ predicate OK (e.g.checkIfExternalUrl) registerFaExtraEnvIpc: env/harness trust, not preload IPCzodinpackage.jsondependencies- Vitest:
shared/_tests/+ registrar tests for invalid payloads
When Zod not replacing existing code
- External links: one string + URL check
- Window control, app details, devtools: no structured renderer payload
- Future bulk DB APIs: Zod from start
Testing
- Vitest:
mainScripts/_tests/, per-area_tests/,contentBridgeAPIs/_tests/ - After main changes:
yarn testbatch:verifywhen TS/sources touched
Renderer sandbox
webPreferences:sandbox: true,contextIsolation: true,nodeIntegration: false. Preload → main IPC for privileged work. Electron Process Sandboxing
Window chrome IPC
registerFaWindowControlIpc,registerFaAppDetailsIpc—BrowserWindow.fromWebContents(event.sender)- Preload path:
path.resolve(currentDir, …)from bundled main chunk — no extra..assuming subfolder ofmainScripts/
Security hardening (main)
app://—registerFaAppProtocolWiring: host allowlist +path.relativeguard against traversal outside app root.- IPC sender — invoke handlers validate
event.sender.idmatches registered main window (failsafe path reply, OS-open, packaged DevTools no-op). - Navigation —
will-navigate+setWindowOpenHandlerallowlist on mainBrowserWindow(mainWindowCreationWiring.ts). openExternal—faExternalUrlPredicate: block RFC1918 + link-local targets.- Project paths —
createResolveHardenedFaProjectFilePath(functions/) +faProjectFilePathHardeningWiring.tsbefore open/reconnect; packaged builds omit devELECTRON_MAIN_FILEPATHleak.
Keybind persistence
mainScripts/keybinds/ — overrides, Zod patch, registerFaKeybindsIpc. See fantasia-keybinds.
SQLite and files
.faproject: docs/database/projectDB.md- App JSON:
electron-store— appUserDataKv.md - fantasia-sqlite-main
Types
Shared types → types/. See types-folder.mdc.