Designed for security, extensibility, and clarity.
Fabriq's architecture answers three core questions: where is the agent allowed to write, what is it about to change, and why did this end up in the repo?
Technology stack
Five hard constraints that shape every design decision.
Controlled Writes
All write operations go through typed IPC with schema validation. The renderer never has direct filesystem access. Every state change is auditable.
Contract-First
IPC handlers must register with a Zod schema. Schema validation happens before execution — malformed payloads are rejected at the protocol level, not the application level.
Read/Write Separation
Service layer handles read aggregation and write orchestration. The UI layer never writes to the filesystem directly — it dispatches typed capability calls.
Dimension Isolation
Workspace assets and feature worktrees are separate dimensions. Feature-dimension operations are blocked from writing workspace assets. The shell enforces this boundary.
Replaceable Engine
The engine-client provides a unified interface supporting four modes: subprocess (production), inline (local dev), local (partial), and stub (demo/UI testing).
Agent-Agnostic
The ACP stdio JSON-RPC protocol decouples the shell from any specific agent. OpenCode, Claude Code, or any future ACP-compatible agent — same shell, same controls.
Five-layer architecture
From presentation to infrastructure — each layer has a clear responsibility.
IPC: the typed customs office.
Every capability call passes through a typed, validated channel before it can execute. Renderer → Preload → Main → Engine — each hop enforces a security boundary.
Renderer dispatches
The React renderer calls a typed function on the preload bridge — e.g., desktopApi.engine.runCapability({ id, input }). It never calls engine.run() directly.
Preload validates shape
The preload script checks that the call matches the registered channel allowlist. Unknown channels are silently dropped. The payload type is validated before forwarding.
Main routes with schema check
The main process IPC handler looks up the capability schema (Zod). If the payload doesn't match the schema, the call is rejected with a typed error — no partial execution, no side effects.
Engine executes (or surfaces confirmation)
For destructive capabilities, the engine queues the action and returns a confirmation token to the UI. The user reviews the payload and approves or rejects before the action hits disk.
Four modes, one interface.
The engine-client abstracts away the runtime mode. Services call the same interface regardless of how the engine is deployed.
Subprocess
Full engine capabilities via a separate dapei-engine process. Production path for teams with the engine installed as a sibling.
Inline
Engine runs in-process with the Electron main process. Default mode — no sibling dependency required. Covers most built-in capabilities.
Local
Partial capability set for local development and testing. Good for UI development without the full engine.
Stub
All capabilities return mock responses. UI components can be developed and tested without any engine installed.
