Durable operations and local transport
Phase 2 establishes the command foundation used by later project, runtime, workspace, UI, CLI, and agent adapters.
Operation lifecycle
Every mutation is represented by one durable operation:
queued -> running -> succeeded -> failed -> cancelled -> partially_succeededqueued -> cancelled -> failedTerminal states never transition again. Operation steps and audit events are append-only. State changes use a compare-and-swap update so a concurrent writer cannot silently overwrite another terminal decision.
An idempotency key is unique within a project. Repeating the same request
returns the existing operation and never schedules a second executor. HTTP
mutation adapters require an opaque Idempotency-Key between 8 and 128
characters; application services enforce the durable uniqueness rule.
Scheduling and cancellation
A keyed gate permits one active lifecycle mutation per project. Operations for different projects can execute concurrently. Cancellation is durable before the live executor receives context cancellation, so a daemon restart cannot forget the request.
Daemon shutdown stops accepting requests, cancels active operation contexts, waits for terminal transitions, closes HTTP and IPC listeners, and only then closes SQLite.
Restart behavior
Recovery is deterministic:
| Persisted state | Recovery action |
|---|---|
queued |
Resume through the registered executor. |
queued with cancellation requested |
Mark cancelled. |
running |
Mark failed with DAEMON_RESTARTED; never guess whether an external side effect completed. |
| terminal | Leave unchanged. |
Later runtime executors reconcile observed external state before a user retries an interrupted operation.
Events and replay
Operation events are inserted into the SQLite journal before live publication.
The sequence is monotonic. WebSocket clients reconnect with
/ws/v1/events?after=<last-sequence>. The daemon replays at most 500 events;
system.refresh_required tells a client to refresh query state when that bound
is exceeded. Slow live subscribers are disconnected and recover through replay.
Local transport and browser sessions
CLI traffic uses HTTP semantics over a user-permissioned Unix-domain socket on
macOS and Linux. The platform adapter reserves the Windows named-pipe identity;
the Windows implementation is completed in Phase 18. The socket and database
are mode 0600, and the data directory is 0700.
The loopback browser API is a separate router:
switchyard uirequests a one-time, one-minute bootstrap token over local IPC.- The browser exchanges that token once for an HttpOnly, SameSite=Strict session cookie and an eight-hour CSRF token.
- Browser queries require the session cookie. Mutations also require the CSRF token and an idempotency key.
- WebSockets require the session cookie and an exact same-origin
Origin.
Bootstrap and session responses are not cacheable. Browser responses set a restrictive content-security policy, no-referrer policy, MIME sniffing protection, and frame denial.