Skip to content

Add type annotations to IPC handler parameters#179

Open
JZimz wants to merge 1 commit into
mainfrom
claude/fervent-einstein-XQaMm
Open

Add type annotations to IPC handler parameters#179
JZimz wants to merge 1 commit into
mainfrom
claude/fervent-einstein-XQaMm

Conversation

@JZimz

@JZimz JZimz commented Apr 15, 2026

Copy link
Copy Markdown
Owner

Summary

IPC handler callbacks in src/main/ipc/device.ts and src/main/ipc/sync.ts were accepting parameters typed as implicit any. Since IPC is an important trust boundary between Electron's renderer and main processes, having untyped parameters means TypeScript can't catch bugs where the wrong data is passed or the shape of arguments changes.

  • In sync.ts, the sync:start handler now declares tagIds: string[], deviceId: string, and options: SyncOptions — types that were already imported in the file but not applied to the handler callback.
  • In device.ts, the four handlers that forward arguments to service functions now declare their parameters using the Device type (already used throughout the service layer), making the handler signatures self-documenting and compiler-checked.

This makes the IPC layer consistent: other handlers in the codebase (e.g. settings.ts) already annotate their parameters, so these two files were the odd ones out.

What's better

  • Type safety at the IPC boundary: mismatches between what the renderer sends and what the main process expects will now be caught at compile time rather than at runtime.
  • Readability: the handler signatures now document their contracts without needing to trace through to the underlying service functions.

https://claude.ai/code/session_017mYtaignsX8oCKT17X1fJS

…dlers

IPC handler callbacks in device.ts and sync.ts were receiving parameters
typed as implicit `any`, providing no compile-time safety at the
Electron IPC boundary. This adds explicit types so TypeScript can
catch mismatches between what the renderer sends and what the main
process expects.

https://claude.ai/code/session_017mYtaignsX8oCKT17X1fJS
@charliecreates charliecreates Bot requested a review from CharlieHelps April 15, 2026 05:07

@charliecreates charliecreates Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The added type annotations are an improvement, but IPC remains a runtime trust boundary: typing alone does not prevent malformed or malicious payloads from the renderer. Using broad shapes like Device/Partial<Device> for IPC inputs is permissive and can unintentionally expand what the main process accepts. Adding runtime validation (and narrowing to explicit IPC input types) would materially improve robustness and security.

Summary of changes

Summary of changes

  • src/main/ipc/device.ts

    • Added import type { Device } from '@/types/device'.
    • Annotated IPC handler parameters for device:create, device:remove, device:update, and device:checkDeviceMount (e.g., id: string, data: Device, data: Partial<Device>).
  • src/main/ipc/sync.ts

    • Annotated the sync:start handler parameters as tagIds: string[], deviceId: string, and options: SyncOptions.

Comment thread src/main/ipc/device.ts
Comment on lines +18 to +21
ipcMain.handle('device:create', (_, data: Device) => addDevice(data));
ipcMain.handle('device:remove', (_, id: string) => removeDevice(id));
ipcMain.handle('device:update', (_, id: string, data: Partial<Device>) => updateDevice(id, data));
ipcMain.handle('device:checkDeviceMount', (_, deviceId: string) => checkDeviceMount(deviceId));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These annotations help at compile time, but they don’t protect the IPC trust boundary at runtime. A compromised/buggy renderer can still send arbitrary payloads, and Device / especially Partial<Device> is quite permissive for an externally-provided input.

Consider validating and narrowing IPC payloads (and ideally using input types like DeviceCreateInput / DeviceUpdateInput that only include fields you actually accept) before forwarding into the service layer.

Suggestion

Add runtime validation (e.g., Zod) + tighten accepted input shapes. For example:

  • Define schemas/types for IPC inputs (create/update) rather than using Device/Partial<Device>.
  • Parse inside the handler before calling services.
import { z } from 'zod';

const DeviceCreateSchema = z.object({
  // only the fields you actually accept from the renderer
  name: z.string(),
  // ...
});

type DeviceCreateInput = z.infer<typeof DeviceCreateSchema>;

ipcMain.handle('device:create', (_e, data: unknown) => {
  const input: DeviceCreateInput = DeviceCreateSchema.parse(data);
  return addDevice(input);
});

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with a minimal validation + input-type tightening pass for these handlers.

Comment thread src/main/ipc/sync.ts
Comment on lines +22 to 24
ipcMain.handle('sync:start', (_, tagIds: string[], deviceId: string, options: SyncOptions) =>
startSync(tagIds, deviceId, options)
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same concern here: the new types improve readability and catch mistakes in main-process call sites, but they don’t validate what arrives over IPC. If startSync assumes invariants (non-empty tagIds, allowed option values, etc.), it’s safer to enforce them at the handler boundary and fail fast with a clear error.

Suggestion

Validate IPC inputs before calling startSync, even if it’s just minimal guards (or ideally a schema).

ipcMain.handle('sync:start', (_e, tagIds: unknown, deviceId: unknown, options: unknown) => {
  if (!Array.isArray(tagIds) || !tagIds.every((t) => typeof t === 'string')) throw new Error('Invalid tagIds');
  if (typeof deviceId !== 'string') throw new Error('Invalid deviceId');
  // validate options similarly (or use a schema)
  return startSync(tagIds, deviceId, options as SyncOptions);
});

Reply with "@CharlieHelps yes please" if you'd like me to add a commit that introduces a small schema/guard layer for sync:start.

@charliecreates charliecreates Bot removed the request for review from CharlieHelps April 15, 2026 05:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants