Architecture

How Electron process boundaries protect a local study workspace.

Processes and trust

The sandboxed React renderer presents the workspace. A typed preload bridge exposes invoke calls and validated event subscriptions. Main owns files, credentials, provider processes, native dialogs, and persistent services.

IPC registration validates the current window’s main-frame sender, request schema, and response schema. Shared Zod contracts describe data that crosses the boundary. Moodle views stay sandboxed and never gain the preload bridge’s app capabilities.

Sandboxed renderer connects through validated IPC to main services, which own SQLite, the library, Moodle, and optional AI providers.React rendererSandboxed · No NodePreload bridgeTyped invoke + eventsIPC validationSender + Zod schemasMain servicesSQLite WALLocal libraryMoodleOpt-in AI

SQLite, files, and cache

Main owns one synchronous node:sqlite connection. Forward-only numbered migrations carry checksums and create backups before disk upgrades. Repositories use bound values, foreign keys, and savepoints.

Originals and converted Markdown are files in the contained library. Document and chat FTS5 trigram indexes support local search. A killable search worker bounds document queries. Account-scoped Moodle TTL caches distinguish fresh, stale, and offline results.

Study and reading services

Moodle services validate site discovery, account identities, capabilities, and responses. Planner services own tasks, goals, exams, plans, and reminders. Main applies explicitly approved agent proposals against current state.

Documents validate source signatures and coordinate on-demand conversion. Provider adapters normalize streaming events. Chat services own request identity, cancellation, history branches, and transactional message persistence.

Startup and shutdown

Main acquires a single-instance lock before opening user data. Saved-key decryption, converters, and CLI execution wait until needed or explicitly approved.

Shutdown rejects new work, aborts and persists chats, stops providers and workers, flushes persistence, and then closes SQLite. Services join this bounded coordinator instead of leaving detached work.

Source reference