mirror of
https://github.com/Pandipipas/scoreko-electron-dev.git
synced 2026-06-06 05:32:06 +00:00
feat: add comprehensive architecture documentation and migration plan for refactor sessions
This commit is contained in:
@@ -0,0 +1,420 @@
|
||||
# Target Architecture
|
||||
|
||||
## Objective
|
||||
|
||||
The target architecture keeps the application small and explicit. Electron should remain a thin shell that owns desktop lifecycle, launches NodeCG, loads local dashboards, manages updates, and shuts down cleanly.
|
||||
|
||||
The target is not a full rewrite. It is a gradual extraction of responsibilities from `main.ts` into testable modules.
|
||||
|
||||
## Target Structure
|
||||
|
||||
```text
|
||||
src/main/
|
||||
app/
|
||||
bootstrap.ts
|
||||
application-controller.ts
|
||||
paths.ts
|
||||
shutdown-service.ts
|
||||
config/
|
||||
runtime-config.ts
|
||||
windows/
|
||||
window-service.ts
|
||||
navigation-policy.ts
|
||||
nodecg/
|
||||
runtime-provisioner.ts
|
||||
nodecg-process-service.ts
|
||||
platform-process-killer.ts
|
||||
updates/
|
||||
update-service.ts
|
||||
update-config.ts
|
||||
update-download.ts
|
||||
update-schema.ts
|
||||
logging/
|
||||
logger.ts
|
||||
shared/
|
||||
result.ts
|
||||
src/shared/
|
||||
types/
|
||||
config.ts
|
||||
```
|
||||
|
||||
`shared/result.ts` is optional and should be added only if it removes repeated error-handling noise.
|
||||
|
||||
`src/shared/types/config.ts` should contain only types that are genuinely shared across process boundaries or packages. It should not become a dumping ground.
|
||||
|
||||
## Runtime Flow
|
||||
|
||||
```text
|
||||
Electron entrypoint
|
||||
-> bootstrap app identity, paths, lock, config
|
||||
-> create ApplicationController
|
||||
-> prepare managed NodeCG runtime
|
||||
-> relaunch if first install requires it
|
||||
-> create loading window
|
||||
-> start NodeCG process
|
||||
-> wait for HTTP readiness
|
||||
-> create or show main window
|
||||
-> load NodeCG dashboard URL
|
||||
-> close loading window
|
||||
-> schedule update checks
|
||||
```
|
||||
|
||||
Shutdown flow:
|
||||
|
||||
```text
|
||||
quit requested
|
||||
-> mark controller stopping
|
||||
-> stop update work if needed
|
||||
-> stop NodeCG process tree
|
||||
-> close windows
|
||||
-> allow app exit
|
||||
```
|
||||
|
||||
Activation flow:
|
||||
|
||||
```text
|
||||
activate requested
|
||||
-> if ready, create or show main window
|
||||
-> if not ready, route through readiness-aware startup
|
||||
-> never load dashboard before NodeCG readiness
|
||||
```
|
||||
|
||||
## Module Responsibilities
|
||||
|
||||
### `app/bootstrap.ts`
|
||||
|
||||
Owns Electron entrypoint side effects:
|
||||
|
||||
- Set app name.
|
||||
- Set app paths.
|
||||
- Acquire single-instance lock.
|
||||
- Register Electron app event handlers.
|
||||
- Instantiate services.
|
||||
- Delegate startup and shutdown to `ApplicationController`.
|
||||
|
||||
Rules:
|
||||
|
||||
- Keep this file thin.
|
||||
- Do not put business logic here.
|
||||
- Do not make it responsible for update parsing, process killing, or window option construction.
|
||||
|
||||
### `app/application-controller.ts`
|
||||
|
||||
Owns high-level lifecycle state.
|
||||
|
||||
States:
|
||||
|
||||
```text
|
||||
idle
|
||||
preparing
|
||||
starting
|
||||
ready
|
||||
stopping
|
||||
stopped
|
||||
failed
|
||||
```
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Coordinate runtime preparation.
|
||||
- Coordinate NodeCG startup and readiness.
|
||||
- Coordinate loading and main windows.
|
||||
- Coordinate update scheduling.
|
||||
- Coordinate activation.
|
||||
- Coordinate shutdown.
|
||||
|
||||
Rules:
|
||||
|
||||
- State transitions must be explicit.
|
||||
- Shutdown must be idempotent.
|
||||
- Activation must not bypass readiness.
|
||||
- Controller tests should not require real Electron where avoidable.
|
||||
|
||||
### `app/paths.ts`
|
||||
|
||||
Owns pure path construction:
|
||||
|
||||
- Electron `userData` derived paths.
|
||||
- Managed runtime path.
|
||||
- Safe temp locations.
|
||||
- Any path constants shared by startup and provisioning.
|
||||
|
||||
Rules:
|
||||
|
||||
- No Electron side effects.
|
||||
- No filesystem writes.
|
||||
- Pure functions only.
|
||||
|
||||
### `config/runtime-config.ts`
|
||||
|
||||
Owns runtime configuration:
|
||||
|
||||
- Parse environment variables.
|
||||
- Parse static config.
|
||||
- Define defaults.
|
||||
- Return typed runtime config.
|
||||
|
||||
Rules:
|
||||
|
||||
- Parse once.
|
||||
- Validate early.
|
||||
- Do not read environment variables throughout the application.
|
||||
|
||||
### `windows/window-service.ts`
|
||||
|
||||
Owns Electron window creation and window lifecycle.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Create loading window.
|
||||
- Create main window.
|
||||
- Apply secure `webPreferences`.
|
||||
- Apply devtools policy.
|
||||
- Register permission handlers.
|
||||
- Delegate navigation decisions to `navigation-policy`.
|
||||
|
||||
Rules:
|
||||
|
||||
- No NodeCG process logic.
|
||||
- No updater logic.
|
||||
- No runtime provisioning logic.
|
||||
|
||||
### `windows/navigation-policy.ts`
|
||||
|
||||
Owns pure navigation decisions.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Allow approved local NodeCG origins.
|
||||
- Block external navigation.
|
||||
- Block unexpected new-window attempts.
|
||||
- Normalize URL parsing.
|
||||
|
||||
Rules:
|
||||
|
||||
- Prefer `URL` parsing.
|
||||
- Keep policy testable without Electron.
|
||||
- Do not use broad string-prefix allow checks as the primary control.
|
||||
|
||||
### `nodecg/runtime-provisioner.ts`
|
||||
|
||||
Owns managed runtime installation and replacement.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Validate bundled runtime source.
|
||||
- Install runtime into `userData`.
|
||||
- Replace managed runtime safely.
|
||||
- Preserve `cfg`, `db`, and `logs`.
|
||||
- Report whether relaunch is needed.
|
||||
|
||||
Rules:
|
||||
|
||||
- User-owned data must not be deleted.
|
||||
- Runtime replacement must be predictable and test-covered.
|
||||
|
||||
### `nodecg/nodecg-process-service.ts`
|
||||
|
||||
Owns NodeCG process lifecycle.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Validate runtime before launch.
|
||||
- Start NodeCG with `ELECTRON_RUN_AS_NODE`.
|
||||
- Capture process output.
|
||||
- Wait for HTTP readiness.
|
||||
- Stop the process.
|
||||
- Delegate platform-specific process-tree termination.
|
||||
|
||||
Rules:
|
||||
|
||||
- Do not build platform kill commands here.
|
||||
- Do not create windows here.
|
||||
- Do not schedule updates here.
|
||||
|
||||
### `nodecg/platform-process-killer.ts`
|
||||
|
||||
Owns OS-specific process-tree termination.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Terminate a process tree on Windows.
|
||||
- Terminate a process tree on POSIX systems.
|
||||
- Validate process IDs before command construction.
|
||||
- Normalize process-kill errors.
|
||||
|
||||
Rules:
|
||||
|
||||
- Keep platform branches here.
|
||||
- Test command construction.
|
||||
- Keep inputs narrow and typed.
|
||||
|
||||
### `updates/update-service.ts`
|
||||
|
||||
Owns update orchestration.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Schedule update checks.
|
||||
- Fetch update metadata through a helper.
|
||||
- Validate metadata through schema helpers.
|
||||
- Select the correct platform asset.
|
||||
- Ask the user before installing.
|
||||
- Delegate download work.
|
||||
- Start installer only after validation and download success.
|
||||
|
||||
Rules:
|
||||
|
||||
- Do not trust remote metadata.
|
||||
- Do not mix dialogs with JSON parsing.
|
||||
- Do not mix installer execution with download streaming.
|
||||
|
||||
### `updates/update-config.ts`
|
||||
|
||||
Owns update settings:
|
||||
|
||||
- Feed URL.
|
||||
- Current app version.
|
||||
- Platform selection.
|
||||
- Development-mode behavior.
|
||||
|
||||
Rules:
|
||||
|
||||
- Keep production and development behavior explicit.
|
||||
- Do not silently downgrade security in production.
|
||||
|
||||
### `updates/update-download.ts`
|
||||
|
||||
Owns download behavior:
|
||||
|
||||
- Validate URL protocol.
|
||||
- Download to a safe temp path.
|
||||
- Write atomically.
|
||||
- Return a typed result.
|
||||
|
||||
Rules:
|
||||
|
||||
- No dialogs.
|
||||
- No installer execution.
|
||||
- No remote metadata interpretation.
|
||||
|
||||
### `updates/update-schema.ts`
|
||||
|
||||
Owns runtime validation:
|
||||
|
||||
- Update metadata shape.
|
||||
- Asset shape.
|
||||
- Version field presence.
|
||||
- URL field validity before download selection.
|
||||
|
||||
Rules:
|
||||
|
||||
- Unknown remote JSON must be validated before use.
|
||||
- Invalid metadata must fail closed.
|
||||
|
||||
### `logging/logger.ts`
|
||||
|
||||
Optional thin logging boundary.
|
||||
|
||||
Rules:
|
||||
|
||||
- Add only if it improves consistency.
|
||||
- Do not introduce a large logging framework.
|
||||
- Keep logs useful for startup, process, update, and shutdown diagnostics.
|
||||
|
||||
## Electron Decisions
|
||||
|
||||
- Keep Electron main as the only privileged process.
|
||||
- Keep Node.js unavailable to web content.
|
||||
- Keep custom renderer absent unless a concrete feature requires one.
|
||||
- Keep preload absent unless a desktop API must cross into web content.
|
||||
- Treat windows as untrusted web surfaces even when loading local NodeCG dashboards.
|
||||
|
||||
Required `BrowserWindow` security posture:
|
||||
|
||||
```text
|
||||
nodeIntegration: false
|
||||
contextIsolation: true
|
||||
sandbox: true
|
||||
webSecurity: true
|
||||
```
|
||||
|
||||
Additional decisions:
|
||||
|
||||
- Deny permissions by default.
|
||||
- Control devtools by environment.
|
||||
- Block external navigation by default.
|
||||
- Block unexpected new windows.
|
||||
- Review CSP options for NodeCG-hosted content, but do not break dashboards to satisfy theoretical policy.
|
||||
|
||||
## IPC Decisions
|
||||
|
||||
Current target:
|
||||
|
||||
- No IPC.
|
||||
- No preload.
|
||||
- No exposed desktop API.
|
||||
|
||||
Future IPC, if needed:
|
||||
|
||||
```text
|
||||
src/main/ipc/
|
||||
channels.ts
|
||||
register-handlers.ts
|
||||
validators.ts
|
||||
src/shared/ipc/
|
||||
types.ts
|
||||
```
|
||||
|
||||
IPC must be:
|
||||
|
||||
- Explicitly justified by a product requirement.
|
||||
- Channel allowlisted.
|
||||
- Payload validated at runtime.
|
||||
- Typed at compile time.
|
||||
- Narrow in capability.
|
||||
|
||||
IPC must not expose:
|
||||
|
||||
- Raw `ipcRenderer`.
|
||||
- Filesystem primitives.
|
||||
- Process primitives.
|
||||
- Shell execution.
|
||||
- Update installation primitives.
|
||||
- Arbitrary NodeCG process controls.
|
||||
|
||||
## Security Decisions
|
||||
|
||||
Security controls to preserve:
|
||||
|
||||
- No Node.js in web content.
|
||||
- Context isolation enabled.
|
||||
- Sandbox enabled.
|
||||
- No IPC surface by default.
|
||||
- Local navigation only.
|
||||
|
||||
Security controls to add:
|
||||
|
||||
- Explicit `webSecurity: true`.
|
||||
- Permission handler that denies by default.
|
||||
- Explicit devtools policy.
|
||||
- Strong update metadata validation.
|
||||
- Strong update asset URL validation.
|
||||
- Safe temporary download paths.
|
||||
- Atomic download finalization.
|
||||
- Platform process-kill isolation.
|
||||
|
||||
## What This Architecture Should Feel Like
|
||||
|
||||
Future maintainers should be able to answer these questions quickly:
|
||||
|
||||
- Where does startup happen?
|
||||
- Where is NodeCG launched?
|
||||
- Where is readiness checked?
|
||||
- Where are windows created?
|
||||
- Where is navigation allowed or denied?
|
||||
- Where are updates validated?
|
||||
- Where is shutdown coordinated?
|
||||
- Where does platform-specific process killing live?
|
||||
|
||||
If a future change makes those answers harder, it is moving against the target architecture.
|
||||
Reference in New Issue
Block a user