Documentation
Architecture
Execution boundaries, request flow, persistence, and extension points across the desktop, sidecar, mobile companion, and documentation site.
Processes and trust boundaries
Tauri owns native window integration, secure credential commands, menus, updates, and sidecar lifecycle. Its webview runs the SolidJS application. The compiled Bun sidecar opens the database and serves HTTP on 127.0.0.1 with an operating-system-assigned port. The frontend does not open SQLite.
The sidecar's entry point is apps/sidecar/src/main.ts. It creates the HTTP server, builds the application layers, probes /api/health, and then prints a JSON readiness event containing the chosen port. Logs are routed to stderr so stdout remains available for the shell protocol.
The mobile companion reaches an explicitly paired desktop gateway. Its native transport and device credentials are separate from the desktop webview's loopback connection. The documentation Worker is a separate deployment and has no implicit connection to a user's desktop.
Library dependencies
@cadcamfun/core contains CAD, drawing, and CAM computation. It depends on Effect for schemas and boundary integration; algorithmic loops are ordinary TypeScript. @cadcamfun/api imports core types and schemas to declare HTTP inputs, outputs, errors, and streams.
@cadcamfun/db owns the application database service, schema, and migration logic. The sidecar combines it with core, API, AI, plugin SDK, VCS, and workflow packages. Its repositories use the database service; handlers delegate to repositories and services.
The desktop imports both @cadcamfun/api and @cadcamfun/core. It uses the API at runtime through an Effect client and uses core geometry in CAD/CAM features and the viewport. Mobile depends on the API package and wraps companion requests in its client. The standalone nikcli plugin discovers the running application's action catalogue over HTTP rather than importing backend implementations.
HTTP request lifecycle
- The webview obtains the sidecar connection from the native shell.
apps/desktop/src/app/client.tsbuilds an Effect HttpApi client with bearer authorization and an optional account session token.packages/api/src/client.tssupplies a reusable contract client for other consumers.apps/sidecar/src/layers.tsassemblesServedApi, handlers, authorization, CORS, and shared service layers.- The handler validates contract inputs, resolves services, performs computation or persistence, and returns the declared success or error representation. Streaming endpoints preserve their declared stream protocol.
CORS permits Tauri production origins and HTTP loopback origins used in development. It does not replace authorization. The API exposes several response envelope styles; consumers must follow each endpoint's schema rather than assume every response has the same shape.
Service lifecycle and storage
Effect layers acquire the database and shared services within the application scope. The database layer creates its parent directory, enables WAL and foreign keys, optionally applies migrations, and wraps query failures with an operation name. Finalization attempts a truncating WAL checkpoint and closes the SQLite handle.
The DatabaseLive layer selects dataDir/cadcamfun.db. A migration folder must be supplied to apply migrations at startup. AI credentials, plugin state, VCS objects, workflow execution, and file storage are handled through their respective service interfaces; storage details are described on their module pages.
The local Studio in packages/web/script/studio-server.ts is an additional Bun process. It opens a configured existing application database directly and serves authenticated overview data on loopback port 4396. Its development proxy and cookie sessions are independent of the Tauri sidecar connection.
Live project events (pull requests, commits, workflow runs, and assistant session phases) are published through an in-process event service. A new subscriber first receives up to the 20 most recent matching events and then live ones, optionally filtered by project and event type (apps/sidecar/src/services/live-events.ts).
Extension boundaries
There are two plugin integrations. The application plugin SDK defines manifests, capabilities, activation, and host contracts. The nikcli bridge exposes registered CAD/CAM actions to an external assistant. Installing a plugin through an HTTP registry route is a separate operation from activating a module in the runtime host.
Workflow parsing and scheduling live in packages/workflow. Service-backed steps are registered by sidecar layers, while pure project and CAM steps can run with their supplied inputs. VCS computes object hashes, diffs, merges, and GitHub transport operations in its library; sidecar services connect those operations to project persistence.
The web documentation assistant retrieves rendered documentation and can publish guide artifacts when storage is configured. It answers documentation questions; it does not inherit the CAD/CAM application's local project access.
Connection and credential boundaries
| Credential | Purpose | Boundary |
|---|---|---|
| Application bearer token | Admit the local application to protected sidecar routes. | Generated/supplied for the sidecar launch; the webview obtains it through the native connection. |
x-session-token | Select the account acting behind the admitted application. | An absent, invalid, expired, or orphaned session falls back to the local profile. |
| Companion device token | Admit an individually paired phone to gateway routes. | Checked by the separate HTTPS gateway and its method/path allow-list. |
| AI bridge token | Expose permitted actions for a single project to an external agent. | Admits the two action bridge endpoints and enforces read or read/write scope. |
| Provider API key | Authenticate outbound model calls. | Managed by the sidecar credential service; not a substitute for application authorization. |
| GitHub token | Perform a requested mirror operation. | Provided for that call through x-github-token; not project snapshot data. |
Authorization is layered. Passing the bearer middleware does not prove ownership of a particular drawing or project; handlers and repositories check those resources. Pairing similarly does not turn the phone into an unrestricted sidecar client. Consult the specific endpoint and companion policy before choosing a credential.
The authorization adapter is apps/sidecar/src/http/authorization.ts. Companion and bridge decisions live in their own services. Keeping those paths separate lets a lost device or an integration token be revoked without replacing an AI provider's secret.
Failure isolation
Failures before the readiness event belong to sidecar initialization: configuration, database upgrade, service construction, or HTTP startup. Failures after readiness may be specific to a provider, filesystem operation, endpoint, or client session. The shell's lifecycle and the webview's connection-retry budget are distinct; inspect both when a restart changes the listening port.
A disconnected AI stream does not necessarily stop its server-side conversation. Recover the session state before resending an editing instruction. A failed workflow does not roll back its triggering commit. An unsuccessful remote push does not erase local history. These distinctions prevent a network failure from being handled as though a persistent operation never occurred.
For a failing API request, record its method, path, status, endpoint ID, and relevant non-secret identifiers. Compare the running /api/openapi.json with the documentation contract snapshot when client and server versions differ. Avoid troubleshooting with a token from a previous sidecar launch.
Architecture snapshot by source path
| Area | Where it lives | What to read first |
|---|---|---|
| Desktop shell (Rust) | apps/desktop/src-tauri/src/ | sidecar.rs (supervisor), commands.rs, updater.rs, menu.rs, tray.rs, secrets.rs |
| Desktop UI | apps/desktop/src/ | app/, features/ (cad, cam, ai, chat, projects, toolpaths, plugins, …), viewport/, shared/ |
| Sidecar entry | apps/sidecar/src/main.ts | Ready handshake, layers in layers.ts, configuration in config.ts |
| HTTP handlers | apps/sidecar/src/http/ | One file per group, e.g. toolpath-generator.ts, ai.ts, kv.ts |
| Services and repositories | apps/sidecar/src/services/, repos/ | cam-program.ts, companion.ts, auth-tokens.ts, storage.ts |
| Contract | packages/api/src/ | index.ts, groups/, errors.ts, client.ts |
| Kernel | packages/core/src/ | cad/history.ts, cad/sketch.ts, cam/kernel/, cam/post/ |
| Assistant | packages/ai/src/ | actions/, tools/, nikcli/, prompts/ |
| Storage | packages/db/src/ | index.ts, upgrade.ts, schema.ts |
| History | packages/vcs/, packages/workflow/ | Repository API, merge, workflow schema |
| Companion | apps/mobile/ | app/ routes, lib/ connection and pairing |
Trace: from launch to first request
- Tauri starts and the supervisor in
sidecar.rsgenerates a random token. - It spawns
sidecar-<triple>withCADCAMFUN_TOKEN,CADCAMFUN_DATA_DIRandCADCAMFUN_MIGRATIONS_DIR. - The sidecar reads its configuration, opens SQLite (WAL, foreign keys), backs up and migrates if needed, and builds its service layers.
- It binds
127.0.0.1on an ephemeral port and prints a JSON ready line on stdout. The supervisor waits up to 60 s for it. - The supervisor emits
sidecar-status{ state: "ready", port }; the webview callsget_sidecar_endpointfor{ baseUrl, token }. - The webview builds
ApiClient.layer({ baseUrl, token })and starts loading projects.
If the sidecar exits, the supervisor restarts it once and announces the new port; a second failure leaves the status at failed. On quit, the supervisor writes the shutdown line, waits 2 s, and then reaps the process; the database layer checkpoints the WAL as its scope closes.
Trace: a manufacture request
- The CAM workspace captures the drawing elements and stock and calls
POST /api/toolpaths/manufacture. - The bearer middleware admits the request; the body is decoded against
CamKernelRequest. runKernelRequestinservices/cam-program.tscallscam.kernel.jobOfSnapshot; preparation issues become a 400.cam.kernel.runJobplans or follows operations, computes cutting data, generates toolpaths, posts NC for the machine's dialect and replays it on voxel stock to evaluate claims.- The result is decoded against
CamKernelResultand returned. Nothing is stored until the client saves a toolpath with a portable document, at which point the sidecar reruns the captured request and compares.