docs: Enhance documentation across multiple modules for clarity and structure

- Updated CONFIGURATION.md to improve navigation and added mermaid diagrams for better visualization of processes.
- Revised IPC_ARCHITECTURE.md to clarify the security model and added diagrams to illustrate the architecture.
- Improved README.md files in core-api, core-events, core-i18n, and core-storage for consistency and clarity, including better descriptions and structural enhancements.
This commit is contained in:
Firman Ramdhani
2026-05-29 16:21:25 +07:00
parent 9f1158653a
commit d3eb242ebe
7 changed files with 373 additions and 301 deletions
+76 -61
View File
@@ -1,3 +1,5 @@
[← Back to Root](../../../README.md)
# IPC Architecture & Security Model
The Secure Communication Blueprint.
@@ -23,44 +25,56 @@ The desktop wrapper enforces a **strict privilege separation** between three exe
### Trust Level Matrix
| Context | Trust Level | Privilege Scope | Security Guarantee |
|---|---|---|---|
| **Main Process** | Fully Trusted | Unrestricted Node.js access: filesystem, network, printers, OS APIs, child processes | Only code authored by the engineering team executes here |
| **Preload Script** | Controlled | Restricted to `ipcRenderer.invoke()` and `ipcRenderer.send()` — no direct Node.js access | Executes in a **Hermetically Sealed Context** — isolated from both the Main Process globals and the Renderer's DOM |
| **Renderer** | Untrusted | Standard browser sandbox — zero Node.js API surface | Designated as a **Zero-Trust Environment** — may execute third-party code, npm packages, or XSS payloads |
| Context | Trust Level | Privilege Scope | Security Guarantee |
| ------------------ | ------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Main Process** | Fully Trusted | Unrestricted Node.js access: filesystem, network, printers, OS APIs, child processes | Only code authored by the engineering team executes here |
| **Preload Script** | Controlled | Restricted to `ipcRenderer.invoke()` and `ipcRenderer.send()` — no direct Node.js access | Executes in a **Hermetically Sealed Context** — isolated from both the Main Process globals and the Renderer's DOM |
| **Renderer** | Untrusted | Standard browser sandbox — zero Node.js API surface | Designated as a **Zero-Trust Environment** — may execute third-party code, npm packages, or XSS payloads |
### Process Topology
```
┌──────────────────────────────────────────────────────────────────┐
│ MAIN PROCESS [Fully Trusted] │
│ │
│ UNRESTRICTED PRIVILEGES │
│ Filesystem · Network · Printers · Native APIs · Child Processes │
│ Auto-Updater · OS Integration · System Notifications │
│ │
│ ipcMain.handle('channel', handler) ← Command handlers │
│ ipcMain.on('channel', handler) ← Event listeners │
│ webContents.send('channel', data) ← Downstream push │
├───────────── Non-Bypassable Isolation Boundary ─────────────────┤
│ PRELOAD SCRIPT [Secure Gateway] │
│ │
│ HERMETICALLY SEALED CONTEXT │
│ Performs Interface Narrowing: transforms broad IPC capabilities │
│ into a minimal, auditable API surface. Acts as the sole │
│ authorized mediator between trusted and untrusted contexts. │
│ │
│ contextBridge.exposeInMainWorld('electronAPI', { ... }) │
├───────────── Non-Bypassable Isolation Boundary ─────────────────┤
│ RENDERER [Zero-Trust Environment] │
│ │
│ UNTRUSTED WEB CONTENT │
│ Standard browser sandbox. Zero access to: require, __dirname, │
│ process, fs, child_process, net, os, ipcRenderer. │
│ │
│ ONLY authorized interaction vector: │
│ window.electronAPI.methodName(args) │
└──────────────────────────────────────────────────────────────────┘
```mermaid
graph TD
%% ─── Styling Definitions (Dark-Mode Friendly Enterprise Palette) ───
classDef trustedLayer fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#0f172a
classDef gatewayLayer fill:#f0fdf4,stroke:#10b981,stroke-width:2px,color:#064e3b
classDef untrustedLayer fill:#fef2f2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d
classDef functionNode fill:#e2e8f0,stroke:#64748b,stroke-width:2px,color:#0f172a
%% ─── Subgraphs ───
subgraph Main ["MAIN PROCESS [Fully Trusted]"]
M_DESC["Unrestricted Node.js Privileges"]
IPC_MAIN_H[ipcMain.handle]
IPC_MAIN_O[ipcMain.on]
end
subgraph Preload ["PRELOAD SCRIPT [Secure Gateway]"]
P_DESC["Hermetically Sealed Context (Interface Narrowing)"]
CTX_BRIDGE{contextBridge.exposeInMainWorld}
end
subgraph Renderer ["RENDERER [Zero-Trust Environment]"]
R_DESC["Standard Browser Sandbox (No Node.js APIs)"]
E_API([window.electronAPI])
end
%% ─── Flow & Relationships ───
E_API ===>|Only Authorized Vector| CTX_BRIDGE
CTX_BRIDGE --->|Transforms to narrow IPC calls| IPC_MAIN_H
CTX_BRIDGE --->|Transforms to narrow IPC calls| IPC_MAIN_O
%% ─── Apply Styles ───
class Main trustedLayer;
class Preload gatewayLayer;
class Renderer untrustedLayer;
class M_DESC,P_DESC,R_DESC,IPC_MAIN_H,IPC_MAIN_O functionNode;
class CTX_BRIDGE gatewayLayer;
class E_API untrustedLayer;
%% ─── Subgraph Backgrounds (Transparent for Native GitHub Support) ───
style Main fill:transparent,stroke:#3b82f6,stroke-width:2px,stroke-dasharray: 5 5
style Preload fill:transparent,stroke:#10b981,stroke-width:2px,stroke-dasharray: 5 5
style Renderer fill:transparent,stroke:#ef4444,stroke-width:2px,stroke-dasharray: 5 5
```
The Preload Script functions as a **Secure Gateway** that performs **Interface Narrowing** — it transforms the broad, unrestricted IPC capabilities of the Main Process into a deliberately narrow, type-safe API surface. The renderer communicates with native functionality **exclusively** through this gateway. There are no alternative paths, no escape hatches, and no backdoors.
@@ -69,12 +83,12 @@ The Preload Script functions as a **Secure Gateway** that performs **Interface N
These settings are declared in `BrowserWindow.webPreferences` and are **non-negotiable**:
| Setting | Value | Enforcement |
|---|---|---|
| `contextIsolation` | `true` | The Preload executes in a hermetically sealed V8 context. The renderer **cannot** access `require()`, Node.js globals, or any variable from the preload's scope. |
| `nodeIntegration` | `false` | **Zero** Node.js API surface in the renderer. `fs`, `child_process`, `os`, `net`, and all built-in modules are completely unavailable. |
| `sandbox` | `true` | The renderer process runs inside a **Chromium OS-level sandbox**, restricting system calls and file access at the kernel level. |
| `webSecurity` | `true` | The same-origin policy is **strictly enforced**, preventing cross-origin data exfiltration from the renderer. |
| Setting | Value | Enforcement |
| ------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `contextIsolation` | `true` | The Preload executes in a hermetically sealed V8 context. The renderer **cannot** access `require()`, Node.js globals, or any variable from the preload's scope. |
| `nodeIntegration` | `false` | **Zero** Node.js API surface in the renderer. `fs`, `child_process`, `os`, `net`, and all built-in modules are completely unavailable. |
| `sandbox` | `true` | The renderer process runs inside a **Chromium OS-level sandbox**, restricting system calls and file access at the kernel level. |
| `webSecurity` | `true` | The same-origin policy is **strictly enforced**, preventing cross-origin data exfiltration from the renderer. |
---
@@ -82,8 +96,7 @@ These settings are declared in `BrowserWindow.webPreferences` and are **non-nego
Every native feature in this architecture **must** follow the Three-Step Bridge — a Standard Operating Procedure (SOP) that ensures traceability, type-safety, and auditability across the entire IPC surface.
> [!IMPORTANT]
> **Deterministic Synchronization**: Maintaining parity between the Main Process handler, the Preload Gateway exposure, and the TypeScript interface declaration is **mandatory**. A mismatch between any two of the three layers will result in either a **Type-Safety Gap** (silent failures in development) or a **Runtime Regression** (crashes in production).
> [!IMPORTANT] > **Deterministic Synchronization**: Maintaining parity between the Main Process handler, the Preload Gateway exposure, and the TypeScript interface declaration is **mandatory**. A mismatch between any two of the three layers will result in either a **Type-Safety Gap** (silent failures in development) or a **Runtime Regression** (crashes in production).
### Step 1: Register the Handler — Main Process
@@ -134,6 +147,7 @@ contextBridge.exposeInMainWorld('electronAPI', electronAPI);
```
**Non-negotiable rules:**
- **Never** expose `ipcRenderer` directly — this is a **Catastrophic Failure** pattern.
- **Never** expose `ipcRenderer.on` without cleanup — use `createEventSubscription()`, which returns an unsubscribe function for React `useEffect` lifecycle management.
- **Always** declare explicit TypeScript types for all function signatures.
@@ -160,17 +174,18 @@ The following is the **complete, authoritative registry** of all authorized IPC
### Printer Subsystem
| Channel | Direction | Pattern | Payload | Access Control |
|---|---|---|---|---|
| `printer:get-list` | Renderer → Main → Renderer | `invoke` / `handle` | Returns `ElectronPrinterInfo[]` | Read-only hardware enumeration |
| `printer:print` | Renderer → Main → Renderer | `invoke` / `handle` | Accepts `ElectronPrintOptions`, returns `{ success, failureReason? }` | Controlled hardware invocation |
| Channel | Direction | Pattern | Payload | Access Control |
| ------------------ | -------------------------- | ------------------- | --------------------------------------------------------------------- | ------------------------------ |
| `printer:get-list` | Renderer → Main → Renderer | `invoke` / `handle` | Returns `ElectronPrinterInfo[]` | Read-only hardware enumeration |
| `printer:print` | Renderer → Main → Renderer | `invoke` / `handle` | Accepts `ElectronPrintOptions`, returns `{ success, failureReason? }` | Controlled hardware invocation |
**Main process handler:** `setupPrinterIPC()` in `src/main/index.ts`
**Preload Gateway surface:**
```typescript
getPrinters: () => ipcRenderer.invoke('printer:get-list')
print: (options?) => ipcRenderer.invoke('printer:print', options)
getPrinters: () => ipcRenderer.invoke('printer:get-list');
print: (options?) => ipcRenderer.invoke('printer:print', options);
```
**React consumption hook:** `useElectronPrinter()` in `apps/web/src/hooks/use-electron-printer.ts`
@@ -179,16 +194,16 @@ print: (options?) => ipcRenderer.invoke('printer:print', options)
### Auto-Updater Subsystem
| Channel | Direction | Pattern | Payload | Access Control |
|---|---|---|---|---|
| `updater:check` | Renderer → Main | `invoke` / `handle` | Returns update check result | Read-only version query |
| `updater:install` | Renderer → Main | `send` / `on` | No payload | Privileged: quits app and installs |
| `updater:checking` | Main → Renderer | `send` | No payload | Status notification |
| `updater:available` | Main → Renderer | `send` | `UpdateInfo { version, releaseDate, releaseNotes }` | Status notification |
| `updater:not-available` | Main → Renderer | `send` | `UpdateInfo` | Status notification |
| `updater:progress` | Main → Renderer | `send` | `ProgressInfo { percent, bytesPerSecond, transferred, total }` | Progress telemetry |
| `updater:downloaded` | Main → Renderer | `send` | `UpdateInfo` | Status notification |
| `updater:error` | Main → Renderer | `send` | Error message string | Error telemetry |
| Channel | Direction | Pattern | Payload | Access Control |
| ----------------------- | --------------- | ------------------- | -------------------------------------------------------------- | ---------------------------------- |
| `updater:check` | Renderer → Main | `invoke` / `handle` | Returns update check result | Read-only version query |
| `updater:install` | Renderer → Main | `send` / `on` | No payload | Privileged: quits app and installs |
| `updater:checking` | Main → Renderer | `send` | No payload | Status notification |
| `updater:available` | Main → Renderer | `send` | `UpdateInfo { version, releaseDate, releaseNotes }` | Status notification |
| `updater:not-available` | Main → Renderer | `send` | `UpdateInfo` | Status notification |
| `updater:progress` | Main → Renderer | `send` | `ProgressInfo { percent, bytesPerSecond, transferred, total }` | Progress telemetry |
| `updater:downloaded` | Main → Renderer | `send` | `UpdateInfo` | Status notification |
| `updater:error` | Main → Renderer | `send` | Error message string | Error telemetry |
**Main process handlers:** `setupAutoUpdaterIPC()` + `setupAutoUpdaterEvents()` in `src/main/index.ts`
@@ -283,7 +298,7 @@ contextBridge.exposeInMainWorld('ipc', ipcRenderer);
contextBridge.exposeInMainWorld('require', require);
```
**Threat:** The renderer can `require('child_process').exec('rm -rf /')`. A single XSS vulnerability in *any* dependency — including transitive ones — escalates to **full filesystem access, credential theft, reverse shells, and data exfiltration**.
**Threat:** The renderer can `require('child_process').exec('rm -rf /')`. A single XSS vulnerability in _any_ dependency — including transitive ones — escalates to **full filesystem access, credential theft, reverse shells, and data exfiltration**.
**Classification:** **Total System Compromise**
@@ -294,7 +309,7 @@ contextBridge.exposeInMainWorld('require', require);
```typescript
// VIOLATION: Catastrophic Failure — Complete Boundary Collapse
new BrowserWindow({
webPreferences: { nodeIntegration: true, contextIsolation: false }
webPreferences: { nodeIntegration: true, contextIsolation: false },
});
```