Skip to content

RPC and Application Boundary

The desktop UI is a client of the Go core even when both are shipped in one desktop application.

Why keep the boundary real

  • the Go core can be exercised through tests/CLI without Electron;
  • renderer security remains narrow;
  • future remote control does not require moving filesystem/process logic into the client;
  • contracts are generated instead of duplicated by hand.

Contract technology

Current direction: Protobuf + ConnectRPC with generated Go and TypeScript clients.

The technology is an implementation choice; the invariant is a generated shared contract and a clear client/core ownership boundary.

Commands versus CRUD

Mutation endpoints express domain intent.

Good:

text
CreateTask
MakeTaskReady
StartTask
StopTask
ResolveDecision
RequestChanges
ApproveTask
SubmitPlanRevision
ApprovePlan
RunVerification

Avoid unrestricted patch endpoints that let the renderer force illegal states.

Queries may be resource/view oriented:

text
GetProject
ListTasks
GetTaskWorkspace
ListOpenDecisions
GetReview
ListActivityPage

Streaming

Use server streaming/subscription only for bounded live updates. Initial state comes from a snapshot/query. Historical pages use queries rather than pretending a subscription is an archive API.

Electron lifecycle

Electron main launches the bundled Go core, obtains/creates a loopback endpoint and random session credential, monitors its lifecycle, and shuts it down cleanly. The renderer talks to the core through a narrow authenticated path.

Do not expose arbitrary command execution through preload.

Compatibility

Client and core may eventually update independently. Capability/version negotiation belongs in the protocol rather than assuming matching versions forever. We do not need a large compatibility matrix on day one, but generated contracts and explicit capability fields make evolution possible.

Forge is local-first. The docs are part of the product engineering system.