Files
scoreko-electron-dev/docs/refactor/ARCHITECTURE_RULES.md
T

6.5 KiB

Architecture Rules

Purpose

These rules define the constraints for future refactor sessions. They are intentionally practical: every rule should either protect behavior, reduce Electron risk, or keep the codebase easier to test.

Core Rules

Preserve The Product Model

  • The app remains an Electron main-process wrapper around a local NodeCG runtime.
  • NodeCG continues to be launched locally.
  • Dashboards continue to load from approved local HTTP origins.
  • The managed runtime continues to live under Electron userData.
  • Runtime provisioning must preserve cfg, db, and logs.

Avoid Unnecessary Architecture

  • Do not add a renderer architecture unless a user-facing feature requires it.
  • Do not add a preload script unless desktop APIs must be exposed to web content.
  • Do not add IPC for organizational neatness.
  • Do not introduce broad frameworks for lifecycle, dependency injection, logging, or configuration.
  • Add an abstraction only when it removes real complexity or isolates a risky boundary.

Keep Behavior Stable

  • Preserve current behavior before reorganizing files.
  • Write tests around existing behavior before extracting lifecycle code.
  • Move files separately from behavior changes.
  • Run typecheck, tests, and lint after meaningful refactor steps.

TypeScript Rules

  • Do not use any.
  • Prefer explicit domain types at module boundaries.
  • Validate unknown external input before narrowing.
  • Keep pure functions pure.
  • Prefer narrow interfaces over large service objects.
  • Avoid global mutable state outside bootstrap or explicit controllers.

Electron Rules

BrowserWindow Defaults

Every application window must use secure defaults:

nodeIntegration: false
contextIsolation: true
sandbox: true
webSecurity: true

Additional rules:

  • Devtools availability must be controlled by environment or explicit config.
  • Permission requests must be denied by default.
  • New-window behavior must be blocked unless explicitly allowed.
  • Navigation must be allowlisted.
  • Remote content must not gain Node.js access.

Preload Rules

Current decision:

  • No preload script is required.

If a preload becomes necessary:

  • Keep it minimal.
  • Expose APIs only through contextBridge.
  • Do not expose raw ipcRenderer.
  • Do not include business logic in preload.
  • Validate all payloads crossing the boundary.
  • Treat preload as part of the security boundary, not as a convenience layer.

Renderer Rules

Current decision:

  • There is no custom renderer.

If a renderer is added later:

  • It must not assume Node.js access.
  • It must communicate through typed, validated IPC only.
  • It must not own NodeCG process lifecycle.
  • It must not bypass navigation or permission policies.

IPC Rules

Current decision:

  • No IPC layer is needed.

If IPC becomes necessary:

  • Define all channel names in one module.
  • Use explicit request and response types.
  • Validate every payload at runtime.
  • Use allowlisted handlers only.
  • Never expose filesystem, process, shell, or update primitives directly.
  • Never expose raw Electron APIs to web content.
  • Keep handlers small and delegate to tested services.
  • Return structured errors instead of throwing raw implementation details across IPC.

Example target shape:

src/main/ipc/
  channels.ts
  register-handlers.ts
  validators.ts
src/shared/ipc/
  types.ts

Do not create this structure until IPC is genuinely needed.

NodeCG Runtime Rules

  • Keep NodeCG process ownership in the main process.
  • Launch NodeCG with ELECTRON_RUN_AS_NODE.
  • Validate the runtime installation before launching it.
  • Wait for HTTP readiness before loading dashboards.
  • Treat process stdout and stderr as diagnostic information only.
  • Stop the full process tree on app shutdown.
  • Keep platform process termination behind an adapter.

Filesystem Rules

  • Filesystem behavior must live behind domain modules.
  • Runtime provisioning must never delete user-owned cfg, db, or logs.
  • Downloads must stay inside safe temporary directories.
  • Paths from config, remote metadata, or user-controlled sources must be validated before use.
  • Avoid scattering path construction across unrelated modules.

Update Rules

  • Treat remote update metadata as untrusted.
  • Validate update JSON with a runtime schema.
  • Validate asset URLs before download.
  • Prefer https: URLs for production updates.
  • Fail closed when metadata is malformed.
  • Download to a safe temporary file.
  • Finalize downloads atomically.
  • Keep fetch, validation, download, dialog, and install steps separate.
  • Fix user-facing encoding issues when touching updater text.
  • Do not execute downloaded installers unless validation has succeeded.

Navigation Rules

  • Allow only expected NodeCG dashboard origins.
  • Prefer explicit URL parsing over string prefix checks.
  • Block external navigation by default.
  • Block unexpected new-window attempts.
  • Keep navigation policy testable as pure logic where possible.

Configuration Rules

  • Parse configuration once.
  • Keep configuration access centralized.
  • Avoid reading environment variables throughout the codebase.
  • Keep runtime defaults explicit.
  • Ensure build scripts and app runtime agree on shared constants where appropriate.

Process Rules

  • Child process management must sit behind a small interface.
  • Platform-specific kill behavior must be isolated.
  • Windows process termination must validate numeric PIDs before command construction.
  • Shutdown must be idempotent.
  • Repeated quit events must not trigger duplicate process cleanup.

Testing Rules

  • Test pure path and URL functions directly.
  • Test lifecycle states without launching real Electron where possible.
  • Test updater validation with malformed metadata.
  • Test navigation allow and block cases.
  • Test process shutdown edge cases.
  • Add integration-style coverage only where unit tests cannot represent the Electron behavior.

Refactor Rules

  • Do not refactor unrelated modules in the same change.
  • Do not change formatting across the repository unless requested.
  • Do not move folders and change behavior in the same step.
  • Prefer small commits or small reviewable patches.
  • Leave existing passing tests intact unless the product behavior intentionally changes.

Security Baseline

The secure baseline is:

  • No Node.js in web content.
  • No preload unless needed.
  • No IPC unless needed.
  • Local navigation only.
  • Deny permissions by default.
  • Validate remote update data.
  • Validate downloaded update assets.
  • Keep process and filesystem access in main-process services only.