1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
# Worklog
## Current Task Goal
Move Claudomator UI auth into Doot: replace Apache proxy rules with a Doot-side
reverse proxy, gating `/claudomator/*` behind Doot's session auth.
## Status: PLAN — awaiting user confirmation
---
## Plan: Claudomator UI behind Doot auth
### Architecture
```
Browser → Apache (SSL) → Doot :38080 → [session auth] → Claudomator :8484
```
Apache currently proxies `/claudomator/*` directly to :8484 with no auth.
Goal: move the proxy into Doot so session middleware gates it.
Two processes, two systemd units — unchanged.
Claudomator base-path already hardcoded to `/claudomator` in web/index.html.
### Step 1 — Doot: add `ClaudomatorURL` config
- `internal/config/config.go` — add `ClaudomatorURL string` (env: `CLAUDOMATOR_URL`, default: `http://127.0.0.1:8484`)
- Tests: default + override
### Step 2 — Doot: HTTP + WebSocket reverse proxy handler
- New file: `internal/handlers/claudomator_proxy.go`
- `httputil.ReverseProxy` for normal requests; WS connection hijacker for upgrades
- Director strips `/claudomator` prefix from both `URL.Path` AND `URL.RawPath` (handles encoded chars in task names/IDs)
- Do NOT set `ReadDeadline`/`WriteDeadline` on hijacked WS connections (kills long-lived task monitoring)
- Preserve `Service-Worker-Allowed` response header so SW scopes correctly under `/claudomator`
- Tests: HTTP forward, prefix strip, WS tunnel
### Step 3 — Doot: restructure CSRF middleware, mount proxy
- `cmd/dashboard/main.go`: move CSRF out of global middleware into a route group
- `/claudomator` → redirect 301 to `/claudomator/` (trailing slash; prevents asset fetch breakage)
- `/claudomator/api/webhooks/github` → exempt from `RequireAuth` (GitHub POSTs have no session; endpoint does its own HMAC validation)
- `/claudomator/*` route: `RequireAuth` only (no CSRF — SPA doesn't send Doot's CSRF token)
- All other routes: wrapped in CSRF group (behavior unchanged)
### Step 4 — Apache: remove Claudomator proxy rules
- Remove 4 lines from `/etc/apache2/sites-enabled/doot.terst.org-le-ssl.conf`
- `apache2ctl configtest && apache2ctl graceful`
### Step 5 — Smoke tests
- Unauthenticated `/claudomator/` → 302 to `/login`
- `/claudomator` (no slash) → 301 to `/claudomator/`
- Authenticated: UI loads, task CRUD works, WS live updates, log streaming
- GitHub webhook POST to `/claudomator/api/webhooks/github` → not redirected to login
### Risks
- CSRF restructure: verify all existing Doot routes still pass their tests after moving CSRF to a group
- SecurityHeaders CSP already allows `wss: ws:` — no change needed
- Claudomator :8484 remains accessible on localhost without auth (acceptable for now)
- Future: `/claudomator/api/*` technically CSRF-vulnerable from other origins; mitigate later by injecting `XSRF-TOKEN` cookie
---
## Previous Task: ADR-007 — Epic→Story→Task hierarchy (IN_PROGRESS)
### Completed Items
| Step | Description | Test / Verification |
|------|-------------|---------------------|
| Phase 1 | Doot dead code removal: Bug struct, BugToAtom, bug store methods, bug handlers, bug routes, bugs.html template, TypeNote, AddMealToPlanner stub | `go test ./...` in /workspace/doot — all pass |
| Phase 2 | Claudomator project registry: `task.Project` type, storage CRUD + UpsertProject, seed.go, API endpoints, legacy fields removed | `TestCreateProject`, `TestListProjects`, `TestUpdateProject`, `TestProjects_CRUD` |
| Phase 3 | Stories data model: Story struct + ValidStoryTransition, stories table, CRUD, story API endpoints | committed 5081b0c |
| Phase 4 | Story execution and deploy: checkStoryCompletion → SHIPPABLE, story branch checkout, POST /api/stories/{id}/branch | committed 15a46b0 |
| Phase 5 | Story elaboration: POST /api/stories/elaborate + approve, SeedProjects at startup, GetProject on executor Store interface | committed bc62c35 |
### Pending (Claudomator tasks queued)
| Task ID | Phase | Status |
|---------|-------|--------|
| f39af70f-72c5-4ac1-9522-83c2e11b37c9 | Phase 6: Doot — Claudomator integration | QUEUED |
### Key Files Changed (Phases 1–5)
#### Claudomator
- `internal/task/project.go` — Project struct
- `internal/task/story.go` — Story struct + ValidStoryTransition
- `internal/task/task.go` — removed Agent.ProjectDir/RepositoryURL/SkipPlanning
- `internal/storage/db.go` — projects + stories tables, CRUD
- `internal/storage/seed.go` — SeedProjects
- `internal/api/projects.go`, `stories.go`, `elaborate.go` — handlers
- `internal/executor/executor.go` — GetProject on Store interface, RepositoryURL resolution
- `internal/cli/serve.go` — SeedProjects at startup
#### Doot
- Bug feature removed entirely (models, handlers, store, routes, template, migration)
- `internal/models/atom.go` — SourceBug, TypeBug, TypeNote, BugToAtom removed
|