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

148 lines
9.0 KiB
Markdown

# 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.js``server/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.