diff --git a/TECHSTACK.md b/TECHSTACK.md new file mode 100644 index 0000000..39d2b2a --- /dev/null +++ b/TECHSTACK.md @@ -0,0 +1,158 @@ +# Tech Stack — BizGaze Connect + +> Living document. **Last updated: 2026-10-27.** Update this file whenever a dependency, platform, service, or +> tool is added/removed/version-bumped. See [Maintaining this file](#maintaining-this-file) and the +> [Changelog](#changelog) at the bottom. + +## What this project is + +BizGaze Connect is a self-hosted team **chat + meetings + calling** product (evolved from a remote +screen-sharing/"remote-access" tool, whose agent console still lives in the repo). One backend serves a web app +and is wrapped by native mobile (Capacitor) and desktop (Electron) shells. The UI loads live from the server, so +web changes deploy **without** rebuilding the native apps. + +**Architecture style:** thin, dependency-light Node backend (custom modules, no web framework) + a single-page +vanilla-JS web UI + native shells that wrap the web and add native capabilities (push, calling, screen capture, +file access). Real-time via WebSockets; meeting media via WebRTC (P2P mesh, or LiveKit SFU when enabled). + +--- + +## Backend (server) + +- **Runtime:** Node.js — `engines` requires **>= 22.5**; the Docker image is **`node:24-alpine`**. +- **HTTP/HTTPS:** Node built-in `http`/`https` modules. **No Express/Koa/Fastify** — a small custom router + (`routes.js`) maps `"METHOD /path"` to handlers; static files + authenticated downloads via `static.js`. +- **WebSockets:** [`ws`](https://github.com/websockets/ws) `^8.18` (`WebSocketServer` on `/ws`) — chat, presence, + meeting signaling (SDP/ICE relay + consent). +- **Structure (server/):** `server.js` (wiring), `routes.js` (HTTP JSON API), `repos.js` (all SQL / data access), + `signaling.js` (WS), `calls.js`, `chat.js`, `presence.js`, `session.js`/`auth.js`, `push.js`, `livekit.js`, + `media.js`, `mailer.js`, `webhooks.js`, `bizgaze.js` (BizGaze identity provider), `directory.js`, `config.js`. +- **Media tooling:** **ffmpeg** (in the image) for server-side video poster thumbnails. + +## Data layer + +- **Database:** **PostgreSQL 16** (`pg` `^8.13`). This is the only backend — **SQLite was retired 2026-08-12**; + one schema source of truth at `server/db/schema.pg.sql`. Selected via `DB_BACKEND=pg` / `DATABASE_URL`. +- **DB access:** hand-written SQL through an async adapter (`server/dbx.js`, `server/db/`), centralized in + `repos.js`. No ORM. +- **Cache / pub-sub:** **Redis 7** (`redis` `^4.7`) for cross-instance real-time fan-out (chat/presence) — + **optional**, only when `PUBSUB_BACKEND=redis`; default is in-memory single-instance (`pubsub.js`). + +## Real-time & media + +- **WebRTC** for calls/meetings: built-in **P2P mesh** by default; **LiveKit SFU** when configured. +- **LiveKit SFU server:** `livekit/livekit-server:**v1.9**` (Docker, `sfu` compose profile, dormant unless + `LIVEKIT_*` env is set). Server mints per-user JWT join tokens (`server/livekit.js`). +- **LiveKit clients:** + - Web: self-hosted **`livekit-client` ~2.20** UMD (`server/public/vendor/livekit-client.umd.min.js`). + - iOS: **LiveKit Swift SDK `2.15.3`** (SPM, `client-sdk-swift`, product `LiveKit`). + - Android: **LiveKit Android SDK** (`io.livekit:livekit-android`) — planned for native-calling Increment 2. + +## Web client (`server/public/`) + +- **Vanilla JavaScript SPA** — `home.html` is the app (large single file with inline JS). **No framework, no + bundler, no build step.** Supporting files: `icons.js` (shared Lucide icon set via `ic()`), `connect.html` + (embed), `sw.js` (service worker), `bizconnect-toast.js`. +- **PWA:** installable; service worker for Web Push + offline shell. +- **Icons:** Lucide (shared set, rendered through `ic()`); no emoji as control icons. + +## Mobile app (`mobile/`) — Capacitor + +- **Framework:** **Capacitor 8** (`@capacitor/core` `^8`) — a native shell (iOS WKWebView / Android WebView) + loading the remote web UI from `https://remote.bizgaze.com`. **Not Flutter/React Native.** +- **Official plugins (`^8`):** App, Camera, Filesystem, Keyboard, Share, Push Notifications, Splash Screen, + Status Bar; **community** `@capacitor-community/safe-area` `^8`; `@capacitor/assets` `^3` (icons/splash). +- **Local/custom plugins (`mobile/plugins/`):** + - `native-call` — native calling. **iOS:** Swift, CallKit + PushKit (VoIP) + LiveKit Swift SDK (native media, + video tiles, screen-share via a ReplayKit broadcast extension), on-device live transcription + (`SFSpeechRecognizer`). **Android:** Java, full-screen incoming-call UI over the lock screen + a + `FirebaseMessagingService` woken by high-priority FCM data messages (native LiveKit media = Increment 2, WIP). + - `audio-route` (iOS audio output routing), `media-library` (save to Photos/gallery), `share-inbox` (inbound + share sheet), `file-opener` (native Quick Look / open-with). +- **iOS build:** Capacitor 8 + **SPM** (CocoaPods retired); Xcode 26; a share extension + a broadcast extension. +- **Android build:** JDK **21**, AGP 8.7 / Gradle 8.11, target SDK 36, edge-to-edge; manifest patched in CI + (`mobile/scripts/android-patch.js`) since `mobile/android/` is generated fresh per build. + +## Desktop app (`desktop/`) — Electron + +- **Electron 31** + **electron-builder 24** (NSIS/Windows, DMG/mac, AppImage/Linux) + **electron-updater 6** + (auto-update from `https://remote.bizgaze.com/downloads/`). Wraps the web UI and adds native screen capture. + Optional **`@nut-tree-fork/nut-js`** for input automation. + +## Native host agent (`agent/`) — Electron + +- Legacy **remote-access agent** (`remote-access-agent`): Electron 31 host for screen capture, WebRTC, + consent, and OS input injection (`@nut-tree-fork/nut-js`), signaling over `ws`. + +## Push notifications + +- **Web Push** via VAPID (`web-push` `^3.6`) for browsers/PWA. +- **Android:** Firebase Cloud Messaging (FCM) — Firebase project `bizgaze-connect`; client `google-services.json` + ships in the APK; server uses a service-account key (base64 in `.env`). High-priority **data** messages wake the + native-call plugin for incoming calls. +- **iOS:** Apple Push Notification service (APNs) over HTTP/2 with a token (`.p8`) auth key, including **VoIP + pushes** (PushKit → CallKit) for incoming calls. + +## Infrastructure & deployment + +- **Containers:** Docker + Docker Compose (`Dockerfile`, `docker-compose.yml`). Services: `app` (Node), + `bizgazepg` (Postgres 16), `bizgazeredis` (Redis 7, `scale` profile), `livekit` (SFU, `sfu` profile). +- **Reverse proxy / TLS:** **Nginx Proxy Manager** (external, shared `nginx_proxy_manager_default` network) — + terminates HTTPS and proxies `remote.bizgaze.com` → `app:8090` and `wss://livekit.bizgaze.com` → LiveKit. +- **Persistence:** named Docker volumes — app data (`/data`: uploads, recordings, transcripts, downloads) and + Postgres data. +- **Deploy flow:** push to `master` (Gitea remote `code.bizgaze.com`) → `redeploy.sh` (plink/SSH to the host) → + server-side `deploy.sh` (git pull + docker rebuild + recreate). Secrets live in a gitignored `.env` on the + server (`/opt/bizgaze-support/.env`); see `.env.example`. +- **CI (mobile builds):** **Codemagic** (`codemagic.yaml`) — iOS (`mac_mini_m2`, SPM, publishes to TestFlight) and + Android (`mac_mini_m2`, Node 22, JDK 21, produces an installable debug APK). + +## External integrations + +- **BizGaze** SSO / identity provider + outbound webhook (`bizgaze.js`, `webhooks.js`). +- **SMTP email** via **Nodemailer** `^6.9` (optional) — meeting invites to external participants. +- **GIPHY** GIF search (server-proxied, optional, key-gated). +- **TURN/STUN** for WebRTC NAT traversal (credentials via `.env`). + +## Dev & test tooling + +- **Local DB for tests:** PostgreSQL 16 (local). +- **Browser automation:** `puppeteer-core` driving local Chrome (scratch testing). +- **Android debugging:** `adb` (`platform-tools`). +- **Shell/OS:** developed on Windows; Git Bash + PowerShell; deploy via plink (PuTTY). + +--- + +## Repo layout (key directories) + +| Path | What | +|---|---| +| `server/` | Node backend (API, WS, data access, push, media) | +| `server/public/` | Vanilla-JS web UI (`home.html`, `icons.js`, `sw.js`, `vendor/`) | +| `server/db/` | PostgreSQL schema + DB adapter | +| `mobile/` | Capacitor app (iOS/Android) | +| `mobile/plugins/` | Custom Capacitor plugins (native-call, audio-route, media-library, share-inbox, file-opener) | +| `desktop/` | Electron technician desktop client | +| `agent/` | Legacy Electron remote-access host agent | +| `Dockerfile`, `docker-compose.yml`, `livekit.yaml` | Deploy stack | +| `codemagic.yaml` | Mobile CI (iOS + Android) | +| `redeploy.sh`, `deploy.sh` | Deployment | +| `ARCHITECTURE.md`, `DEPLOY.md`, `CLIENTS.md`, `README.md` | Docs | + +--- + +## Maintaining this file + +Update this document in the **same commit** as any change that alters the stack, specifically when you: + +- add/remove a dependency, or bump a major version (server `package.json`, `mobile/package.json`, + `desktop/package.json`, `agent/package.json`, plugin manifests); +- change a platform/toolchain version (Node, Postgres, Redis, LiveKit, Capacitor, Electron, JDK, Xcode); +- add/remove a service in `docker-compose.yml` or a build workflow in `codemagic.yaml`; +- add a new custom Capacitor plugin or a new external integration. + +Bump the **Last updated** date at the top and add a line to the Changelog below. + +## Changelog + +- **2026-10-27** — Initial tech-stack document created.