Documentation
Dependency Boundaries
This document defines the intended main/renderer/shared boundaries that keep layers from coupling.
They describe the direction new code should follow. They are not lint-enforced today
(eslint.config.js has no import-boundary rule), and the known exceptions are listed below.
Rules
- Renderer must not import main-only modules (e.g.,
src/main/*). - Main must not import renderer-only modules (e.g.,
src/renderer/*). - Shared modules (
src/shared/*) that the renderer imports must avoid Node APIs that are not available in the sandboxed renderer. - IPC is the only bridge between main and renderer. Use typed IPC contracts.
Allowed Imports
- Renderer:
src/shared/*,src/renderer/* - Main:
src/shared/*,src/main/* - Shared:
src/shared/*only (see exceptions)
Known exceptions
src/shared/ also holds some main-process-only utilities. They are never imported by the renderer,
but they break rule 3 and the "shared imports shared only" line:
- Shared modules that import from
src/main/:src/shared/atomicFileOperations.jslazily requires../main/errors/FileSystemErrorand../main/services/DegradedStateTracker.src/shared/fileOperationTracker.jsresolves../main/services/ServiceContainerthrough itsgetContainerclosure.
- Shared modules that use Node or Electron APIs (
fs,os,child_process,electron):atomicFile.js,atomicFileOperations.js,crossPlatformUtils.js,fileOperationTracker.js,logger.js,pathSanitization.js,platformUtils.js,safeStorageEncryption.jsandsecurityConfigPathLimits.js. Some of these are also bundled for the renderer or preload; they guard the Node-only paths at runtime or are swapped for stubs (for examplesecurityConfigPathLimits.preload-stub.js) or webpackresolve.fallbackshims.
When you touch one of these modules, prefer moving main-only logic under src/main/ over adding
more exceptions.
Enforcement
- Prefer IPC channels and payload schemas for cross-process data.
- Review new
src/shared/*imports against the rules above; an import-boundary lint rule would be welcome.