# ADR-006: Claudomator Integration **Status:** IN_PROGRESS **Date:** 2026-03-26 ## Context Claudomator (task executor, story runner) and Doot (personal dashboard) are separate services. The goal is to unify them into a single coherent product: shared visual identity, shared auth, simplified deployment, and eventually shared code. ## Decisions Made ### Auth — Gate via Doot Proxy (DONE) All `/claudomator/*` routes require Doot session auth. Webhooks are exempted. Auth is enforced in Doot's Go proxy middleware before the request is forwarded to Claudomator. Claudomator itself remains auth-free (trusts the proxy). - Implemented: `internal/handlers/claudomator_proxy.go` — `RequireAuth` applied to proxy routes - Claudomator's bearer token mechanism exists but is unused; left in place for future direct API use ### WebSocket Proxy — Go, not Apache (DONE) Claudomator's WebSocket at `/claudomator/api/ws` is proxied by Doot's Go handler (`proxyWebSocket`). Apache was updated to add an explicit `ws://` ProxyPass rule for this path so mod_proxy_wstunnel activates correctly. - Apache vhost tracked at: `deploy/apache/doot.terst.org-le-ssl.conf` - Go proxy handles header stripping, path rewriting, and bidirectional copy ### Visual Design — Rewrite Claudomator UI (IN PROGRESS) Claudomator's UI (vanilla JS SPA) is being rewritten to use Doot's dark glass design system: Inter font, slate-950 bg, glass cards (backdrop-blur, slate-900/80, white/5 border), sky-400 accent. No Tailwind build step — hand-coded CSS. - Story: `55d4a55a` on branch `story/ui-dark-glass-theme` - app.js logic unchanged; only style.css and index.html ### Process Architecture — Two Processes, One Domain (DECIDED, NOT CHANGED) Claudomator and Doot remain separate processes communicating over localhost. The proxy overhead is negligible. Separate processes allow independent restarts — important because Claudomator's executor manages in-flight container tasks. A future move to single-binary (mounting Claudomator's router directly into Doot's mux) is possible but not yet needed. ## Architectural Seams (Decided: Seam 1 → Seam 2) Three integration paths were evaluated (with Gemini, 2026-03-26): ### Seam 1: HTMX Partial Provider (NEXT) Claudomator stays a separate process but begins serving Go `html/template` HTML fragments alongside its JSON API. Doot embeds these via `hx-get="/claudomator/partials/..."`. The reverse proxy stays. SPA components are converted one at a time. - **Pre-requisite:** Visual unification (story `55d4a55a`) — must look the same before templates are merged - **Interface:** HTTP + shared CSS class names - **Unlocks:** Incremental SPA → HTMX migration with no operational risk; sets up Seam 2 - **Deploy coupling:** None (still two independent deploys) ### Seam 2: Shared Library / Single Binary (FUTURE) Claudomator's `internal/storage`, `internal/executor`, `internal/task` refactored as embeddable packages. Doot imports them directly; proxy eliminated; one process. - **Blocker:** Executor manages in-flight container tasks — Doot restart kills them. Requires graceful shutdown in executor pool before this is safe. - **Interface:** Go interfaces (`executor.Pool`, `storage.DB`) - **Unlocks:** Single deploy, no proxy overhead, Doot handlers call task service as local function calls - **Deploy coupling:** High — one binary, one restart ### Seam 3: Shared SQLite (REJECTED) Both processes point at the same DB file (WAL mode). Rejected — schema is a fragile interface, benefit is achievable via existing REST aggregation. ### Comparison | | Current | Seam 1 | Seam 2 | Single Binary | |---|---|---|---|---| | Deploy coupling | Low | Low | High | High | | Runtime complexity | 2 procs | 2 procs | 1 proc | 1 proc | | UI migration path | Hard | Easy (incremental) | Medium | Easy | | In-flight task safety | Safe | Safe | Needs graceful shutdown | Needs graceful shutdown | ## Open / Remaining Questions ### Navigation (DONE) Doot's nav already has a Claudomator tab link (`/claudomator/`) in `web/templates/index.html:86`. ### Seam 1 First Partial: Stories View (PLANNED, not yet started) - **What:** The Stories tab (currently a full SPA panel in Claudomator's `app.js`) becomes a Go template rendered by Doot - **Where it lives:** Doot — a new handler in `internal/handlers/` queries Claudomator's JSON API (`GET /claudomator/api/stories`) and renders HTML directly. No proxy needed for this route. - **Why Stories first:** Simpler structure than the task queue; stories are already surfaced as Doot atoms, so the data model is familiar - **Pre-requisite:** Visual unification story (`55d4a55a`) must ship first - **Trigger:** Plan this story after `55d4a55a` is REVIEW_READY ### Deploy Coordination Two manual deploy commands. Acceptable until Seam 2. ### Doot Atom Source (DONE) Claudomator stories surface as atoms in Doot's task aggregation (commit `b58787c`). ### Structured Acceptance Criteria Story model being extended with named acceptance criteria (story `bf42482d`). ## Consequences - Claudomator is permanently behind Doot's auth — it cannot be accessed directly on port 8484 from the public internet (Apache only exposes doot.terst.org) - The visual unification is a prerequisite for the HTMX partial migration path - The two-process model means deploy order matters: Claudomator must be running for Doot's proxy to work; Doot startup should gracefully degrade if Claudomator is down