Skip to content

Admin Console

Zlatko Lakisic edited this page Aug 4, 2026 · 4 revisions

Admin Console

Always-on ops UI served by the bridge on :8781/admin. Production and dev. Shares the port with Google Desktop OAuth. Source of truth in-repo: docs/CONTRACTS.md § Admin console, docs/DEV_LOOP.md §2, terminal/admin/.

This is an operations console, not the marketing site. Same visual language (dark field, cyan = healthy, amber = degraded / LAN / DEV, red = fail / destructive). Live emblem reuses terminal/kiosk/emblem.js so the rail face matches the hallway panel.


Open it

# SSH tunnel (preferred from the Mac)
LocalForward 8781 127.0.0.1:8781   # in Host comstar
make admin                         # http://127.0.0.1:8781/admin/

# LAN (token required when bound to 0.0.0.0)
# http://<pi-ip>:8781/admin/?token=<COMSTAR_ADMIN_TOKEN>
# or header: X-Comstar-Lan-Token: <token>

On the Pi, prefer systemd EnvironmentFile:

# ~/.config/comstar/admin.env  (mode 0600; never commit)
COMSTAR_ADMIN_BIND_LAN=1
COMSTAR_ADMIN_TOKEN=<secret>

Wire with a drop-in EnvironmentFile=-%h/.config/comstar/admin.env on comstar-bridge.service. Tokens containing ! break raw systemd Environment= lines.


Path split on :8781

Prefix Role Admin token
/admin/* Ops UI + APIs Required when LAN-bound (except health + static assets)
/oauth/google/* Desktop Google OAuth Never
/health Alias → /admin/health None
/kiosk/* Shared emblem/presets for admin ES modules None

Routes

Route Method Auth Meaning
/admin/ GET token if LAN-bound Static UI (favicon.svg, CSS, JS)
/admin/health /health GET none Attention / session / WS snapshot (heal script)
/admin/api/status GET token if LAN-bound Extended status, host metrics, AO/CPAI probes
/admin/api/logs GET token if LAN-bound SSE journalctl --user tail
/admin/api/restart POST token if LAN-bound {unit: bridge|audio|kiosk|stt|health|all}
/admin/api/reboot POST token if LAN-bound {confirm: "reboot"}
/admin/api/sleep POST token if LAN-bound {action: enter|exit}
/admin/inject POST token if LAN-bound Attention inject; 403 unless COMSTAR_ENV=dev
/oauth/google/* * none OAuth start / callback / resend

Restart units are whitelisted (comstar-*.service only).

Token accepted as X-Comstar-Lan-Token (preferred) or ?token=. Resolution order: COMSTAR_ADMIN_TOKENadmin.tokendev.lan_token.

The log panel uses fetch with the auth header (not EventSource), so proxy header injection (e.g. Warpgate) works without putting the token in the URL.


Bind rules

Default bind: 127.0.0.1. Bind 0.0.0.0 when any of:

  1. admin.bind_lan: true and a non-empty admin token, or
  2. COMSTAR_ADMIN_BIND_LAN=1 and COMSTAR_ADMIN_TOKEN (preferred on Pi), or
  3. the WS LAN triple-gate is active, or
  4. Google OAuth would have bound LAN (COMSTAR_OAUTH_BIND_LAN / redirect base)

Admin LAN bind is independent of the WebSocket triple-gate. Ports 8777/8778 still need COMSTAR_ENV=dev + comstar.dev.yaml + dev.lan_token. See Security.

When LAN-bound, the UI shows a permanent amber LAN badge and rule.


UI panels

Panel What you get
Top bar Brand, hostname, LOOPBACK/LAN badge, DEV badge, uptime, live poll dot, clock
Left rail Live emblem (actual attention state), userid, session/reach/sleep/uptime
Health AO, CPAI, STT, kiosk, audio cards + CPU/mem
Actions Restart units, sleep/wake; danger zone: restart all / reboot
Inject Dev only (COMSTAR_ENV=dev): synthetic attention events
Logs Live JSONL tail, unit filter, text filter, pause, wrap, download

Freshness: panels dim when the status poll fails. Unreachable emblem freezes grey with an amber ring.


Dev inject

Same handle(Event) entry point as hardware. Events are tagged src: "injected" in logs.

curl -sS -X POST 'http://127.0.0.1:8781/admin/inject?token=…' \
  -H 'content-type: application/json' \
  -H 'X-Comstar-Lan-Token: …' \
  -d '{"event":"TranscriptReady","text":"What time is it?"}'

Supported events: PersonDetected, PersonAbsent, FaceRecognized, FaceUnknown, WakeWord, SpeechStart, SpeechEnd, TranscriptReady, ResponseReady, PlaybackEnded, Tick, AttentionError, VisionDegraded, VisionRecovered.


Warpgate / reverse proxy notes

If you front :8781 with Warpgate (or similar):

  1. Terminate Warpgate auth for humans.
  2. Inject X-Comstar-Lan-Token: <secret> toward the Pi for /admin/* (except /admin/health, which needs no token).
  3. Pass /oauth/google/* through without requiring the COMSTAR admin token. Keep Google’s registered callback URL aligned with the public host.
  4. Do not buffer /admin/api/logs (SSE).
  5. Do not confuse this token with AO’s x-warpgate-token (orchestration).

Related pages

Clone this wiki locally