Commit Graph

6 Commits

Author SHA1 Message Date
Sravan 3250530596 feat(db): complete async call-site conversion — Phase 3 done, validated on SQLite
The full sync→async conversion is complete and green on the SQLite backend. Every
DB call across the app now awaits the async adapter, so the identical code runs on
Postgres at cutover.

Converted (this commit finishes Phase 3):
- session.js: currentUser/apiKeyFromReq async → 63 route awaits + WS + static.
- routes.js: all ~250 R.* awaited; DTO helpers (namesFor, avatarsFor, buildMsgDTO,
  buildPollDTO, reactionsForMessage, postSystemMessage, pushGroupUpdate,
  issueRefreshToken, provisionFromBizgaze) made async; every `.map(x=>buildDTO(x))`
  restructured to `await Promise.all(...map(async...))` preserving order; `.filter`
  predicates that hit the DB moved to an `asyncFilter` helper; chained
  `R.x.y(...).length/.map/.filter` wrapped as `(await R.x.y(...)).method`; stream
  upload handlers (recording/transcript/attachment) made async.
- calls.js / signaling.js: all call/meeting fns async; leaveMeeting AWAITS
  persistCallHistory + finalizeTranscript BEFORE endCallByRoom (ordering matters —
  fire-and-forget would race the map teardown); WS handle()/cleanup() async with
  .catch guards.
- static.js: authAttachment(Raw) async (the .some carrier check became a loop),
  handleGet async; server.js dispatch catches handler rejections → 500 not a hang.
- media.js backfill, push.js, reminders.js, webhooks.js await their repo calls.

Validation on DB_BACKEND=sqlite: db-smoke 22/22; legacy e2e 80 checks pass with zero
FAILs (throws only at a PRE-EXISTING WS lobby-drift assertion, unrelated). Every
server file `node --check` clean.

Still on the branch — master untouched. Next: Phase 5 (pg backend + ~7 dialect
queries + data migration + Docker Postgres + cutover), then merge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 22:06:27 +05:30
Sravan 8a5409987c perf(video): stream a capped, faststart rendition instead of the raw upload
THE ANSWER to "why does an already-downloaded video still buffer?" — it was never
the download, and it was not the server. Probing the real uploads on the box:

  d0e49e58…  1920x1080  19.4 Mbps   75 MB / 31 s
  ad929d0b…  1920x1080  19.0 Mbps   27 MB / 11 s
  9f4e0865…   720x1584   3.6 Mbps   14 MB / 31 s

To play a 19 Mbps file the client has to SUSTAIN a 19 Mbps download for the whole
clip. No mobile link does, so the <video> buffer drains every few seconds: buffers,
plays, buffers, plays. Server-side disk read was instant and load was 1.7 on 20
cores throughout — the bottleneck is the media itself, not the delivery path.

Second, independent defect: phone MP4s store `moov` AFTER `mdat` (verified on two
uploads), so the player must fetch the file's tail before it can start at all.

Fix — keep the original bytes untouched (that is what the download button serves,
full quality) and build <id>.web.mp4 beside it: longest side capped at 1280,
~2.5 Mbps ceiling, +faststart. Measured on the 19 Mbps file:

  27.3 MB @ 19.0 Mbps  ->  2.55 MB @ 1.78 Mbps   (10.7x less bandwidth)
  transcode took 2.4 s for an 11.5 s clip

- server/media.js (new): probe, decide, 2-at-a-time background queue. Already
  light + correctly sized + faststart => no rendition at all. Light but wrong atom
  order => remux -c copy (seconds, no re-encode). Otherwise re-encode. A rendition
  that lands bigger than the original is discarded. MP4 box-walker for the
  faststart test is unit-checked against known fast/slow files, both directions.
- /stream/<id> serves the rendition, falling back to the original while it is still
  transcoding, so a video is never unplayable. /files/<id> is unchanged and still
  serves the pristine original for download.
- Renditions are queued at upload, and backfilled 15 s after boot for the videos
  that predate this. Range serving is now one shared helper for both routes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 10:49:04 +05:30
Sravan ba8bfc3f46 feat: BizGaze Connect home, BizGaze login, modular backend, /api/v1
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>
2026-06-12 00:40:07 +05:30
Sravan 28f616d829 Added Record screen, transcribe, mobile screen share bug fix. 2026-06-10 16:46:03 +05:30
Sravan 3560e1756e managed TURN (mobile/cellular fix) + UI bug fixes
- server: /api/ice endpoint reads TURN creds from env (TURN_URLS/USERNAME/CREDENTIAL)
- share/connect: load ICE config at page open
- fixes: stop icon, bright chat notification, beep audio-unlock,
  customer screen cleanup on session end, Home link, Remember-me on agent login, Time spent fixed from 90 seconds to actual time spent
2026-06-09 16:47:43 +05:30
sriram b984b55bc0 first commit 2026-06-05 17:29:09 +05:30