# ADR-0004: Workspace state lives in a SQLite-backed FastAPI server from Day 1

**Status:** Accepted (Phase 1; reaffirmed Phase 2)

## Context

Workspace state — column widths, parked tabs, lineage viewport positions,
tweaks panel values — must agree across desktop, mobile, and a hypothetical
second tab on the same machine. The naive option (`localStorage`) silently
diverges across surfaces and persists only as long as the browser cache
survives. Dropbox-syncing a JSON file works for read-mostly state but races
on concurrent writes (Dropbox merges by mtime, not by structured diff).

## Decision

Stand up a small FastAPI server at `127.0.0.1:8431` (`recoil/api/`) that
persists workspace state to SQLite WAL at `~/.recoil/v2_workspace_state.db`
— OUTSIDE Dropbox, on the Studio host. Every persisted shape carries
`schemaVersion: 1`. The server stores `payload_json` opaquely and validates
only the envelope (`schema_version`, `workspace_id`, `payload_json`); shape
validation lives client-side via zod. A LaunchAgent keeps the server up.

## Consequences

Single source of truth for all workspace UI state. Concurrent writes are
serialized at the SQLite WAL boundary. Mobile, desktop, and any future
secondary surfaces hit the same endpoint over Tailscale. The cost: the
console requires the Studio to be reachable. Offline desktop work is not a
goal for v2; mobile needs Tailscale connectivity and graceful retry on
network blip.
