-
Notifications
You must be signed in to change notification settings - Fork 1
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.
# 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.
| 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 |
| 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 (AO probe uses mTLS when enabled); includes ao_mtls + road at_home
|
/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/api/road |
GET/POST | token if LAN-bound | Road VPN phone-home (ADR 0011) |
/admin/api/network |
GET/POST | token if LAN-bound | Wi‑Fi + IPv4 via nmcli (ADR 0012) |
/admin/api/ao_mtls |
GET/POST | token if LAN-bound | AO Reach mTLS pairing (ADR 0013) |
/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_TOKEN → admin.token → dev.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.
Default bind: 127.0.0.1. Bind 0.0.0.0 when any of:
-
admin.bind_lan: trueand a non-empty admin token, or -
COMSTAR_ADMIN_BIND_LAN=1andCOMSTAR_ADMIN_TOKEN(preferred on Pi), or - the WS LAN triple-gate is active, or
- 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.
| 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 |
| Ops tabs | Actions · AO pairing · Road VPN · Network · Logs (same panel) |
| Actions | Restart units, sleep/wake; danger zone: restart all / reboot |
| AO pairing | Enroll / clear / probe AO client certs; status dot on the tab (ADR 0013) |
| Road VPN | Phone-home OpenVPN/L2TP; gray At home when VPN not needed (ADR 0011) |
| Network | Wi‑Fi scan/connect + ethernet/wlan DHCP or static IPv4 (ADR 0012) |
| Inject | Dev only (COMSTAR_ENV=dev): synthetic attention events |
| Logs | Live JSONL tail (Ops → Logs tab): unit filter, text filter, pause, wrap, download |
| Tab | Cyan | Amber / gray | Red |
|---|---|---|---|
| AO pairing | mTLS enabled and PEMs present (paired) | Gray = mTLS disabled in config | Enabled but not paired |
| Road VPN | Tunnel up / healthy | Gray At home (local CIDR; VPN idle by design) | Off-home and down / unhealthy |
GET /admin/api/status exposes ao_mtls: {enabled, paired} and road at_home for the rail.
Ada AO ≥ 1.29 serves HTTPS with required client certs. Primary UX is this tab;
headless alternative: make ao-mtls-enroll TOKEN=….
- Paste a one-time enrollment token from Ada.
- Enroll writes PEMs under
~/.local/share/comstar/ao-mtls/(never commit). - Probe / health use the same client cert + CA trust.
- Clear material to force re-pair (sessions fail closed until re-enrolled when mTLS is enabled).
Config: orchestration.mtls.* + base_url: https://… — Configuration, ADR 0013.
When the Pi has no ethernet and no Wi‑Fi client, the bridge brings up NM SoftAP
comstar-hotspot (SSID COMSTAR-<hostname>, open, Pi at 10.87.65.1/24). The
kiosk admin QR points at that IP, shows the SSID under the QR, and stays visible
while the hotspot is up (even if kiosk debug UI is off). Join the SSID, then scan.
Disable with COMSTAR_HOTSPOT=0. See ADR 0014.
Freshness: panels dim when the status poll fails. Unreachable emblem freezes grey with an amber ring.
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.
If you front :8781 with Warpgate (or similar):
- Terminate Warpgate auth for humans.
- Inject
X-Comstar-Lan-Token: <secret>toward the Pi for/admin/*(except/admin/health, which needs no token). - Pass
/oauth/google/*through without requiring the COMSTAR admin token. Keep Google’s registered callback URL aligned with the public host. - Do not buffer
/admin/api/logs(SSE). - Do not confuse this token with AO’s
x-warpgate-token(orchestration).
- Dev Loop — day-to-day Mac → Pi workflow
- Runbook — ops procedures
- Security — LAN gates, mTLS material, SoftAP
-
Environment Variables —
COMSTAR_ADMIN_*,COMSTAR_HOTSPOT -
Configuration —
orchestration.mtls.*, optionaladmin:YAML - Google Workspace — OAuth on the same port
- Contracts — formal route table
- ADR 0013 · ADR 0014
COMSTAR AI — Not a mystical AI. A tool you engineered — transparent, hackable, fast.
Home · Architecture · Admin Console · Runbook · Contracts
Apache-2.0 · Pre-alpha · Raspberry Pi 4 terminal + local AI server
COMSTAR AI
Start here
Product
Build & configure
Interfaces
- Contracts Overview
- Bridge ↔ Kiosk
- Bridge ↔ Audio
- CodeProject.AI
- AO Reach
- MCP Tools
- Attention State Machine
Features
- Speech (STT/TTS)
- Vision & Face Enrollment
- Directory Identity
- Wake Word
- MCP Topology
- Terminal Control
- Google Workspace
Decisions (ADRs)
- ADR Index
- 0001 Audio Routing
- 0002 Render Path
- 0003 Speech on Ada
- 0004 Terminal Control
- 0005 LDAP Identity
- 0006 House Presence
- 0007 Full-Duplex AEC
- 0008 TTS Engine
- 0009 Proactivity
- 0010 Text Channel
- 0011 Road VPN
- 0012 Admin Network
- 0013 AO mTLS
- 0014 Fallback Hotspot
Operate
Plan
Meta