Files
BizGaze_Remote/CLAUDE.md
T
Sravan ad48829337 Retire the SQLite backend — Postgres is the only engine
The dual backend (SQLite via db.js + Postgres via schema.pg.sql) was a
maintenance foot-gun: a schema change could land on the SQLite path only and
silently 500 every read on prod (it just did, with #18/#13). Production has run
on Postgres for weeks, so SQLite is retired: ONE schema source of truth
(db/schema.pg.sql), no drift possible.

- dbx.js: default DB_BACKEND=pg; an unknown backend now fails loudly at require
  time instead of silently selecting a stale engine.
- Deleted server/db.js, server/db/sqlite.js, server/db/migrate-sqlite-to-pg.js,
  server/scripts/migrate-bizgaze-only.js (all SQLite-only, none in the runtime
  path — the running server loads db/pg.js).
- Tests (e2e, db-smoke) target Postgres now and fail-fast (skip) unless
  DATABASE_URL points at a disposable test DB — never SQLite, never prod.
- Removed the dead DB_PATH env + fixed misleading SQLite comments in the
  Dockerfile / docker-compose (kept the /data volume: it holds
  uploads/recordings/transcripts/downloads, not just the old data.db).
- CLAUDE.md: stack + repo-layout + run-locally updated for Postgres-only.

Runtime is unaffected (prod already sets DB_BACKEND=pg and pg is a prod dep);
this only removes the unused SQLite path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-12 08:20:26 +05:30

9.0 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. npm deps: ws, pg, redis, web-push (+ optional nodemailer).
  • PostgreSQL via the async adapter (server/dbx.jsserver/db/pg.js). SQLite was RETIRED 2026-08-12: there is now ONE schema source of truth, server/db/schema.pg.sql — every schema change goes there (and post-cutover COLUMNS need an explicit ALTER TABLE … ADD COLUMN IF NOT EXISTS, since the file is applied idempotently on every boot and CREATE TABLE IF NOT EXISTS won't alter an existing table).
  • 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, async)
  bizgaze.js     # BizGaze identity provider (validate login, env-gated)
  dbx.js         # async DB adapter facade -> db/pg.js (Postgres; only backend)
  db/pg.js       # Postgres backend; db/schema.pg.sql = the single schema source of truth
  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). ANY schema change goes in db/schema.pg.sql (see stack note). After backend edits, run the tests against a DISPOSABLE Postgres (they no longer bundle SQLite): DATABASE_URL=postgres://…/bizgaze_test node test/db-smoke.js.

Run locally

# Start a local Postgres (or use the compose one), then:
docker compose up -d bizgazepg
cd server && npm install
DB_BACKEND=pg DATABASE_URL=postgres://bizgaze:bizgaze_local@localhost:5432/bizgaze 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/report
  • GET /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= — uploads
  • GET /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 getDisplayMedia screen 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 → getDisplayMedia is called directly from the customer's "Allow" tap (see share.html beginCapture).
  • Recording/transcript use browser MediaRecorder + Web Speech API → Chrome/Edge only.

Production

  • remote.bizgaze.com, Linux, Docker, behind a reverse proxy.
  • Proxy MUST: upgrade /ws with 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

  1. SSO with BizGaze (active): BizGaze becomes the identity provider. It issues a signed token; /sso verifies 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.)
  2. New post-login home (NEXT TASK) — see below.
  3. Persistent chat — 1:1 messaging is BUILT (messages table, /api/v1/messages/*, live delivery over /ws via chat-hello/chat-message, wired into home.html). Group chat is the remaining part.
  4. Meetings (multi-party video) — mesh (P2P) MVP BUILT: in-memory rooms + signaling (meeting-create/join/signal/leave in signaling.js), video-grid UI in home.html's Meeting tab (start/join by 6-digit code, mic/cam toggles, leave). Good for small groups; SFU upgrade is the next step for larger rooms.
  5. 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 --check extracted inline scripts after edits; test against a local node server.js before committing.