Wadsworth — Dashboard Operations Brief
From: Daedalus 🎨
Date: 2026-04-28
Purpose: Routing, config, and monitoring for the Family Dashboard
1. Architecture Overview
family.hoffdesk.com
↓ Cloudflare Tunnel
↓ (Host: family.hoffdesk.com)
↓
titanium-butler:8000 ← main_v2.py (Starlette host routing)
├── family_app (when Host: family.hoffdesk.com)
│ ├── SessionAuthMiddleware ← all routes except /login, /static/
│ ├── auth_router → GET /login, POST /login, GET /me, POST /logout
│ ├── dashboard_router → GET / (dash HTML), GET /family/login/, GET /api/today
│ ├── family_router → /admin/... (family automation)
│ ├── imap_router → IMAP proxy dashboard
│ └── WebSocket endpoints (future)
│
└── blog app (all other hosts)
There is also a second server on port 8001:
titanium-butler:8001 ← Icarus staging API (icarus.core.api)
├── /api/today ← calendar + weather + health JSON
├── /api/event_graph/... ← Event Graph CRUD
├── /system/state ← System state dashboard HTML
└── Jinja2 templates ← index.html.j2 (HTMX version)
Current state: The family.hoffdesk.com app (port 8000) serves a static index.html without the Event Graph cards. The Icarus server (port 8001) has the Jinja2 template with HTMX wiring but lacks auth middleware and isn't behind the tunnel.
2. Routes & Endpoints
Auth (family_app, port 8000)
| Method | Path | Purpose | Status |
|---|---|---|---|
| GET | /family/login/ |
Login page | ✅ Live |
| POST | /login |
Login handler (JSON body) | ✅ Live |
| GET | /me |
Session check | ✅ Live |
| POST | /logout |
Clear session | ✅ Live |
Credentials (from .env):
- matt / hoffdesk-matt-2026 — roles: admin, editor
- aundrea / hoffdesk-aundrea-2026 — roles: family
Dashboard (family_app, port 8000)
| Method | Path | Purpose | Status |
|---|---|---|---|
| GET | / |
Dashboard (requires auth) | ✅ Live |
| GET | /api/today |
JSON: calendar+weather+health | ✅ Live |
Icarus API (port 8001, internal)
| Method | Path | Purpose | Status |
|---|---|---|---|
| GET | /api/today |
Calendar + weather + health JSON | ✅ Live |
| GET | /api/event_graph/stats |
Event Graph aggregate stats | ✅ Live |
| GET | /api/event_graph/recent |
Recent events from graph | ✅ Live |
| GET | /api/event_graph/coordination |
Coordination items | ✅ Live |
| GET | /system/state |
System state dashboard HTML | ✅ Live |
| GET | / or /family/ |
Dashboard HTML (Jinja2, HTMX) | ✅ Live |
| GET | /family/login/ |
Login page | ✅ Live |
Running the Icarus Server
cd /home/hoffmann_admin/.openclaw/workspace/services/icarus
ICARUS_ENV=staging \
PYTHONPATH=/home/hoffmann_admin/.openclaw/workspace/services:$PYTHONPATH \
nohup uvicorn icarus.core.api:app --host 0.0.0.0 --port 8001 --log-level info > /tmp/icarus-api.log 2>&1 &
3. What's Working (Daedalus ✅)
- Family dashboard served at
family.hoffdesk.comwith auth - Login flow: page → POST /login → session cookie → redirect to dashboard
/api/todayreturns calendar (Radicale), weather (wttr.in), health (live pings)- Static assets served at
/static/(style.css, favicon.svg, system-state.css) - Event Graph API endpoints on port 8001
- CSS polish: Event Graph cards, IMAP proxy, iPad responsive (shared/project-docs/dashboard/static/style.css)
4. What Needs Routing / Config (Wadsworth)
Critical
- [ ] Monitor the Icarus server process on port 8001 — start it on boot, restart if it dies
- [ ] ICARUS_ENV must be
stagingfor the assert in api.py line 11 - [ ] PYTHONPATH must include
/home/hoffmann_admin/.openclaw/workspace/servicesfor theicaruspackage to resolve
Config Management
- [ ] HOFFDESK_USERS env var in
.envcontains the credential map — do NOT expose in logs - [ ] SESSION_SECRET_KEY should be set for production (currently defaults to dev-secret)
- [ ] RADICALE_HOST/PORT/USER/PASS — used by dashboard router for calendar data
- [ ] Cloudflare tunnel routes
family.hoffdesk.comtolocalhost:8000
Dashboard Template Path (important)
The dashboard router on port 8000 reads templates from:
/home/hoffmann_admin/.openclaw/shared/project-docs/dashboard/templates/
This is a shared path — if I update templates, they're live immediately. Don't move them.
Event Graph
The Event Graph API runs on port 8002 and feeds into the dashboard. If 8002 is down, /api/today returns empty events gracefully (no crash).
5. Monitoring
Health Check Endpoints
GET http://localhost:8000/health → blog API health
GET http://localhost:8001/api/today → Icarus health (check status fields)
GET http://localhost:8002/health → Event Graph health
GET http://localhost:5232/ → Radicale CalDAV health
What to Watch
- Port 8001 — Icarus API dies if PYTHONPATH is wrong
- Port 8002 — Event Graph API (needs separate startup)
- Radicale on 5232 — calendar source; dashboard degrades gracefully but quietly
- Cloudflare tunnel — if it drops,
family.hoffdesk.comis unreachable
Model Health Watchdog
See shared/processes/model-health-watchdog.md for the model ping spec. Not yet implemented.
6. Quick Commands
# Check dashboard is alive
curl -s -H "Host: family.hoffdesk.com" -o /dev/null -w "%{http_code}" http://localhost:8000/
# Check API response
curl -s -H "Host: family.hoffdesk.com" http://localhost:8000/api/today | python3 -m json.tool
# Restart Icarus API
kill $(lsof -t -i:8001)
sleep 2
cd /home/hoffmann_admin/.openclaw/workspace/services/icarus && \
ICARUS_ENV=staging PYTHONPATH=/home/hoffmann_admin/.openclaw/workspace/services:$PYTHONPATH \
nohup uvicorn icarus.core.api:app --host 0.0.0.0 --port 8001 --log-level info > /tmp/icarus-api.log 2>&1 &
# Check logs
tail -20 /tmp/icarus-api.log
# Test auth flow
curl -s -c /tmp/hcookie.txt -X POST http://localhost:8000/login \
-H "Content-Type: application/json" \
-d '{"username":"matt","password":"hoffdesk-matt-2026"}'
curl -s -b /tmp/hcookie.txt -H "Host: family.hoffdesk.com" http://localhost:8000/
7. URLs
| URL | Destination | Auth |
|---|---|---|
| https://family.hoffdesk.com/ | Family dashboard | Session cookie |
| https://family.hoffdesk.com/family/login/ | Login page | None |
| https://hoffdesk.com/ | Blog (public) | None |
| https://hook.hoffdesk.com/ | Webhooks | Token |
Questions? Ping @Daedalus89Bot on Telegram or drop a note in shared/project-docs/