User-facing - New post-login home (/home): chat rail + Share/Connect (embedded) + Meeting; login lives here when logged out - Landing: "Log in with BizGaze" + no-login screen share - Console replaced by a role-scoped Dashboard (/dashboard): admins see all team sessions, others see only their own; stats + CSV/PDF export - Recordings saved as MP4 (H.264/AAC) with WebM fallback; old .webm still downloadable - Fix: duplicate "Sign in" on the login card Auth / integration - BizGaze as identity provider: /api/login validates against BIZGAZE_LOGIN_URL (env-gated) and provisions a local user - Phase 2 start: /api/v1 alias for all /api routes; Authorization: Bearer accepted across HTTP + WS; login returns a token (for native desktop/mobile clients) Backend refactor (Phase 1, behavior-preserving) - Split server.js into config/lib/session/presence/routes/static/signaling + repos (data-access) + bizgaze (service) - All SQL behind repos.js, tenant-scoped (tenantId == team_id for now) - e2e updated to current flow (21/21 pass before and after) Docs: ARCHITECTURE.md (target architecture + phased plan), CLAUDE.md repo layout, .env.example BIZGAZE_LOGIN_URL Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
7.8 KiB
BizGaze Connect — project brief
Place this file at the repo root (remote-access-app/CLAUDE.md). Claude Code reads
it automatically each session.
What this is
BizGaze Connect — a no-install, browser-based remote support / screen-sharing tool for the BizGaze ecosystem. A customer opens a page, gets a 6-digit code; a signed-in BizGaze agent enters the code, the customer taps Allow, and the agent sees the customer's screen with two-way voice + chat. Live at remote.bizgaze.com. Roadmap: grow into a communication platform (meetings + persistent chat) for registered BizGaze users.
Tech stack (intentionally minimal — keep it this way)
- Node.js >= 22.5, single npm dependency:
ws(WebSocket). - Built-in
node:sqlite(no native modules). DB file:server/data.db. - WebRTC peer-to-peer for media (screen video + voice + data channels).
- No build step, no framework. Each page is a single self-contained HTML file
with inline
<style>and<script>. Do not introduce React/bundlers. - Auth: scrypt password hashing, HttpOnly session cookie. (SSO migration in progress.)
Repo layout
server/
server.js # thin entry: HTTP dispatch + WS attach + listeners (HTTP/HTTPS)
config.js # env + filesystem paths (PORT, dirs, SESSION_TTL)
lib.js # HTTP helpers: json / readBody / parseCookies / now
session.js # currentUser (cookie -> user) + audit()
presence.js # shared in-memory live state (onlineAgents/liveSessions/pendingShares)
routes.js # HTTP JSON API (/api/*, /sso) -> { "METHOD /path": handler } map
static.js # static file serving + authenticated recording/transcript downloads
signaling.js # WebSocket signaling (consent + SDP/ICE relay)
repos.js # data-access layer — ALL SQL lives here (tenant-scoped)
bizgaze.js # BizGaze identity provider (validate login, env-gated)
db.js # node:sqlite schema + idempotent migrations
auth.js # scrypt hashing, token/id generation, TOTP helpers
package.json # { "dependencies": { "ws": "^8.18" }, engines node>=22.5 }
test/e2e.js # 21-check backend e2e (register->login->session->signaling->audit)
public/
index.html # public landing (Log in with BizGaze / share without login)
home.html # post-login shell: chat rail + Share/Connect (iframe) + Meeting (/home)
dashboard.html# login + role-scoped session report (/dashboard, replaces /console)
connect.html # agent: enter code, view screen, control bar (/connect)
share.html # customer: get code, share screen (/share)
home-mockup.html # locked design reference for home
logo.png
recordings/ # saved session recordings (.webm) [created at runtime]
transcripts/ # saved transcripts (.txt) [created at runtime]
Architecture/roadmap detail lives in ARCHITECTURE.md. Backend SQL must go through
repos.js (never inline in routes/signaling). Run node test/e2e.js after backend edits.
Run locally
cd server && npm install && node server.js
# HTTP on :8090 (HTTPS on :8443 only if cert.pem + key.pem exist in server/)
# Env: ALLOW_REGISTRATION=1 opens the first-team registration
First registered user becomes admin; registration then closes (unless ALLOW_REGISTRATION=1).
Key HTTP routes (server.js)
POST /api/register|login|logout,GET /api/me,GET/POST /api/users,POST /api/users/manage,GET /api/setup-state,GET /api/reportGET /api/ice— returns STUN, plus managed TURN only for mobile clients (TURN creds come from env:TURN_URLS,TURN_USERNAME,TURN_CREDENTIAL)POST /api/recording?sessionId=/POST /api/transcript?sessionId=— uploadsGET /recordings/<sid>.webm/GET /transcripts/<sid>.txt— authed downloads (streamed w/ Content-Length)GET /sso?token=— SSO entry (HMAC today; JWT migration planned)- Page routes:
/,/console,/connect,/share
WebSocket signaling (/ws)
liveSessions map (sessionId -> {agentWs, viewerWs, ...}). Message cases:
agent-hello, viewer-connect, consent, share-create, code-connect,
offer/answer/ice-candidate (relayed peer-to-peer), recording, transcript,
end-session. Keepalive ping every 25s. Media never traverses the server.
Current features (all working on desktop)
- Code-based no-install screen share (customer shares, agent views).
- Two-way voice; in-session chat (logged-in sharer's name shown).
- Session recording: agent presses Record; mixes customer screen + both voices;
uploads
.webm; downloadable from the report. Customer sees a "being recorded" banner + live timer. - Auto-transcript: each side runs Web Speech API on its own mic; lines stream to
the agent; combined
.txt(voices + chat) uploaded; downloadable from the report. - Session report: filter by agent/date, CSV + PDF export, pagination (5/page), agent search, recording/transcript download links.
- Agent management (admin invites, roles admin/technician/viewer), remember-me, case-insensitive email, password show/hide, session-end webhook to BizGaze.
Hard constraints (do not try to "fix" these)
- Mobile browsers CANNOT share their screen. Android Chrome and iOS Safari do
not expose
getDisplayMediascreen capture to web pages. Only a native app can capture a phone screen. The share page detects mobile and shows a clear message. (Desktop screen share works fully.) - Screen capture requires a user gesture →
getDisplayMediais called directly from the customer's "Allow" tap (see share.htmlbeginCapture). - Recording/transcript use browser MediaRecorder + Web Speech API → Chrome/Edge only.
Production
remote.bizgaze.com, Linux, Docker, behind a reverse proxy.- Proxy MUST: upgrade
/wswith long timeouts; allow large bodies on/api/recording; not buffer/recordings/downloads. (See IT-HANDOFF-PROXY.md.) - Env vars:
TURN_URLS,TURN_USERNAME,TURN_CREDENTIAL(Metered TURN),SSO_SECRET,BIZGAZE_WEBHOOK_URL,BIZGAZE_LOGIN_URL(identity provider for/api/login),ALLOW_REGISTRATION,DB_PATH,PORT,HTTPS_PORT.
In progress / roadmap
- SSO with BizGaze (active): BizGaze becomes the identity provider. It issues a
signed token;
/ssoverifies it and creates a local session. Supports both "from inside BizGaze" and a "Log in with BizGaze" button at our URL. Waiting on the dev team for: shared secret, token format (JWT preferred), SSO start URL, signup URL, role mapping. (See BizGaze-Connect-SSO-SPEC.md.) - New post-login home (NEXT TASK) — see below.
- Persistent chat (Slack-style 1:1 + group messaging between registered users) — large new system.
- Meetings (multi-party video) — large new system (needs SFU or mesh).
- Downloadable Android app — the only way to support phone screen-sharing.
NEXT TASK: new post-login home (start with a mockup)
After login, replace the current dashboard with a BizGaze Connect "home":
- Left sidebar (Slack-style): list of recent chats/contacts with avatar, name, last-message preview, unread badge. (Mock data first — no chat backend yet.)
- Main area with tabs: Meeting (placeholder "coming soon"), Share Screen (links to the existing share flow), Connect Screen (existing agent connect flow).
- Top bar: BizGaze Connect wordmark (brand blue #1F3B73 / yellow #FFC708, logo.png), profile dropdown (existing pattern in the HTML).
- Build a standalone static mockup first (e.g.
public/home-mockup.html) to lock the layout, then wire the real tabs/sidebar. Keep the single-file, no-framework style.
Conventions
- Brand: blue
#1F3B73, yellow#FFC708, logo at/logo.png. - Single-file HTML pages; reuse the existing
profileHTML()/wireProfile()and brand patterns already in console.html/connect.html. - Always
node --checkextracted inline scripts after edits; test against a localnode server.jsbefore committing.