Границы процессов

Composition root

create-application-services.ts создаёт сервисы один раз и явно передаёт зависимости конструкторам: Глобальных mutable singleton imports в feature-модулях нет. Это позволяет тестировать lifecycle с подменёнными зависимостями.

Системная конфигурация

Настройки пользователя, выбранный storage root, настройки отдельных серверов и флаги миграции находятся в одном config.json. Внутри файла они разделены на settings, storage, servers и migrations. Старые storage-location.json и server-client-settings.json читаются один раз при обновлении, переносятся в общий store и больше не используются. Запись config.json проходит через единый adapter. На Windows он сохраняет атомарную запись electron-store, но умеет повторить замену файла при кратковременном EPERM от антивируса. Несколько экземпляров приложения не могут одновременно менять store: второй процесс останавливается через single-instance lock.

Модуль подготовки сборки

BuildPreparationService — тонкий сценарный координатор. Он владеет только текущей операцией, AbortController и готовым PreparedBuild. Файловая, процессная и presentation-логика вынесена в специализированные сервисы: Координатор выполняет только последовательность:
  1. получает {profile, build, runtime};
  2. получает безопасный storage layout;
  3. передаёт профиль клиента в общий resource pipeline;
  4. передаёт Java runtime в тот же pipeline;
  5. сохраняет PreparedBuild только после обеих финальных проверок;
  6. переводит состояние в ready.
PreparedBuild не отдаётся renderer’у. В нём находятся profile, manifests и абсолютные пути, необходимые только main-процессу.

Модуль запуска игры

GameLaunchService — координатор одного запуска Guardian/Minecraft. Он не обходит файловое дерево, не формирует classpath и не вызывает spawn самостоятельно: Сам координатор:
  • не допускает параллельный запуск;
  • при необходимости вызывает подготовку сборки;
  • передаёт пользовательскую сессию сервису launch plan только в памяти;
  • связывает Guardian events с состоянием, Discord Presence и окнами;
  • восстанавливает UI после любого exit code.
Состояние GameLaunchState:

IPC game API

Preload предоставляет renderer’у только четыре операции:
Renderer не передаёт username, token, Java path, JVM args или policy. Все эти значения main-процесс получает из доверенных сервисов и профиля.

Автоматический сценарий страницы загрузки

При открытии /servers/:serverId/downloads поверх страницы сервера появляется не отдельная страница, а небольшой modal. Feature build-download подписывается на build/game events и вызывает game.launch(serverId). В modal остаются только текущий ресурс, скорость, оставшийся объём и расчётное время. Внутренний async lifecycle продолжается в main, а IPC сразу возвращает текущее состояние.

Сессия и секреты

Access token хранится только в SessionManager и зашифрованном session.json через Electron safeStorage. Он:
  • не доступен renderer’у;
  • не хранится в electron-store;
  • не записывается в Guardian policy;
  • не выводится в debug console;
  • передаётся Minecraft как динамический argument после --.

Отмена

Build service завершает активный Rust-процесс и AbortController. Game service дополнительно хранит stopRequested, поэтому отмена между финальной проверкой и spawn(guardian) не создаст Java-процесс. После запуска остановка Guardian закрывает Windows Job Object и всё дерево Minecraft.