# chat-saiden Web terminal for BT on the MARAUDER mesh. **chat.saiden.dev** lands a browser-native xterm.js session on `claude` CLI (bt7274 cart) running on junkpile, gated by Cloudflare Access with Google OAuth. ## Architecture ``` User browser │ HTTPS ▼ chat.saiden.dev ──┐ Cloudflare edge │ │ │ CF Access │ Google IdP challenge │ (whitelist) │ → reject if not on list │ │ ▼ │ Cloudflare Tunnel │ Zero-trust ingress │ │ ▼ junkpile:7681 │ ttyd (localhost-only, no public bind) │ │ ▼ claude (bt7274) │ marauder MCP gives BT identity + memory + tools ``` **Properties** - No frontend code. ttyd ships xterm.js + WS + theming. Custom Saiden palette via CLI flags. - No auth code. CF Access does Google OAuth + whitelist enforcement before the request ever reaches the tunnel. - ttyd binds `127.0.0.1` only — the public path is *exclusively* through the Tunnel + Access. - Real BT. Not an API impersonation. Full marauder MCP toolkit available in-session. ## Components | Path | Purpose | |------|---------| | `junkpile/ttyd-wrapper.sh` | Launches `claude` with bt7274 cart, with Saiden banner | | `junkpile/ttyd-chat.service` | systemd unit for ttyd (localhost-only bind, Saiden palette) | | `junkpile/cloudflared-chat-saiden.service` | systemd unit for tunnel (token-mode, reads `/etc/cloudflared/chat-saiden.env`) | | `cloudflare/dashboard-setup.md` | Step-by-step: create tunnel + public hostname + Access app + Google IdP + whitelist | | `install.sh` | Junkpile-side installer (ttyd + units + token env stub) | | `deploy.md` | End-to-end deploy walkthrough | **Tunnel mode:** token-based, matches existing junkpile pattern (`cloudflared-mesh`, `cloudflared-tensors-art`). Tunnel ingress lives in the CF dashboard, not in a local config file. Token sits in `/etc/cloudflared/chat-saiden.env` (mode 0640, root:chi). ## Threat model (read before deploying) ttyd-over-claude exposes **shell-equivalent power** on junkpile. The defense is the CF Access whitelist. Treat the whitelist as the security boundary: - **Never** open the Access policy to "any Google account" or "any domain". - **Always** keep `cloudflared-chat-saiden` and `ttyd-chat` localhost-bound. - If the whitelist is ever modified, `auth_verify` the change with the Pilot first. ## Status - [x] ttyd installed on junkpile (1.7.7_11) - [x] ttyd wrapper installed → `~/.local/bin/ttyd-wrapper.sh` - [x] systemd units installed (`ttyd-chat`, `cloudflared-chat-saiden`) - [ ] Tunnel created in CF dashboard → token in `/etc/cloudflared/chat-saiden.env` - [ ] Public hostname `chat.saiden.dev → http://localhost:7681` - [ ] CF Access app + Google IdP + whitelist configured - [ ] WebSocket support enabled on Access app - [ ] `sudo systemctl enable --now ttyd-chat cloudflared-chat-saiden` - [ ] First successful login as adam.ladachowski@gmail.com - [ ] Whitelist denial verified from second Google account