Skip to content

feat(meet): add mom versioning and room music#195

Open
darkside4x wants to merge 7 commits into
ACM-VIT:mainfrom
darkside4x:ds4x/mom-music-system
Open

feat(meet): add mom versioning and room music#195
darkside4x wants to merge 7 commits into
ACM-VIT:mainfrom
darkside4x:ds4x/mom-music-system

Conversation

@darkside4x

@darkside4x darkside4x commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add host-only MoM finalization that versions exported meeting minutes to a configured GitHub repository
  • add room music controls in host settings with off, hosts, and everyone permissions plus /play chat command support
  • add a shared room music player that auto-ducks to 35% volume while someone else is speaking
  • harden music playback by allowing Piped-based search via MUSIC_PIPED_API_BASE and requiring host-only allowlisted HTTPS direct URLs via MUSIC_DIRECT_URL_HOSTS

Security / behavior notes

  • MoM finalization now requires the signed-in host/admin session plus a room-bound SFU auth token
  • direct audio URLs are not accepted from regular attendees and must match the configured allowlist
  • pending /play requests re-check permissions before broadcasting, and /play in DMs stays private instead of starting room-wide music
  • tags were intentionally removed from this scoped PR per follow-up request

Configuration

  • MOM_GITHUB_TOKEN, MOM_GITHUB_REPOSITORY are required for MoM versioning
  • optional MoM settings: MOM_GITHUB_BRANCH, MOM_GITHUB_BASE_PATH
  • optional music settings: MUSIC_PIPED_API_BASE, MUSIC_DIRECT_URL_HOSTS

Validation

  • git diff --check
  • eslint on changed meeting-core and SFU source files
  • attempted web lint/typecheck/test dependency install, but pnpm install is still blocked by registry timeout while fetching dashjs, next, and @next/swc-win32-x64-msvc

spent a lot of water and tokens to review your slop

Greptile Summary

This PR adds versioned meeting minutes and shared room music. The main changes are:

  • Host-only MoM finalization through short-lived SFU authorization and GitHub storage.
  • Room music permissions, /play search, direct-URL restrictions, and slow mode.
  • Shared playback controls with automatic volume ducking during speech.
  • Host ownership synchronization during transfer and automatic promotion.

Confidence Score: 5/5

This looks safe to merge.

Current host authority is checked when MoM authorization is created and consumed. Host ownership is synchronized during transfer and automatic promotion. Music requests reserve slow mode before lookup and reject stale results after stop or permission changes. No blocking issues were found in the changed code.

T-Rex T-Rex Logs

What T-Rex did

  • Recorded a before-interaction video showing the room-music host-controls in their initial state.
  • Recorded an after-interaction capture showing the Hosts and Everyone selection and the resulting shared-player display.
  • The runtime evidence confirms the validation route returned an HTTP 200 response.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
apps/web/src/app/api/conclave/mom/finalize/route.ts Adds authenticated MoM finalization with live SFU authority consumption and GitHub versioning.
packages/sfu/config/classes/Room.ts Adds current-host authorization state, music state, request throttling, and revision tracking.
packages/sfu/server/socket/handlers/adminHandlers.ts Adds host music controls and short-lived MoM finalization authorization.
packages/sfu/server/socket/handlers/chatHandlers.ts Adds /play resolution with permission, slow-mode, membership, and stale-request checks.
packages/sfu/server/socket/handlers/disconnectHandlers.ts Synchronizes host ownership during automatic promotion and clears departing users' music request state.
apps/web/src/app/components/MeetingMusicPlayer.tsx Adds shared room playback controls and automatic volume ducking.

Reviews (7): Last reviewed commit: "merge upstream main into mom music syste..." | Re-trigger Greptile

Comment thread apps/web/src/app/api/conclave/mom/finalize/route.ts
Comment thread packages/sfu/server/socket/handlers/chatHandlers.ts
Comment thread packages/sfu/server/socket/handlers/chatHandlers.ts
@darkside4x

Copy link
Copy Markdown
Contributor Author

Addressed the Greptile findings in fix(meet): tighten mom and music race guards:

  • MoM finalization no longer trusts the 12h join token. The UI now asks the live SFU socket for a 60s mom:finalize token via an admin-only handler, and the API route only accepts that purpose-scoped token plus the signed-in session email.
  • /play slow mode is reserved before the external resolver runs, so concurrent attendee requests cannot both pass the delay check.
  • Room music now has a revision counter. Stop/permission/track changes bump it, and pending /play requests reject if the revision changed while resolving, so a host stop cannot be reversed by a stale pending request.

Validation repeated:

  • git diff --check
  • focused ESLint on changed meeting-core/SFU source files

Web lint is still blocked locally by the incomplete dependency install (eslint-plugin-react-hooks missing after pnpm registry timeouts).

@darkside4x

Copy link
Copy Markdown
Contributor Author

@greptile Please provide a complete summary of the full updated latest PR, along with a confidence score out of 5. Additionally, list any issues or bugs, noting their severity and whether they are fixed or pending, in a tabular format.y are fixed or pending, in a tabular format.

@greptile-apps

greptile-apps Bot commented Jul 12, 2026

Copy link
Copy Markdown

PR #195 — Full Updated Summary

feat(meet): add mom versioning and room music
Last reviewed commit: 8a2abcabb9 | 19 files changed | +1042 / -14 | 2 commits


What this PR does

1. MoM (Minutes of Meeting) Versioning
A new Next.js route POST /api/conclave/mom/finalize lets a host push meeting minutes as a versioned Markdown file to a configured GitHub repository. Auth uses a two-layer approach: a signed-in session (via better-auth) plus a short-lived (60s) mom:finalize JWT issued by the SFU's mom:authorizeFinalize admin-only socket handler. Room IDs are sanitized before being written into the GitHub file path. Rate-limited to 4 calls/minute per user per room, and capped at 512KB per document.

2. Room Music System

  • Three permission levels: off / admin (hosts only) / everyone
  • /play <url or search> chat command; silently skipped if inside a DM
  • Piped API backend for search (MUSIC_PIPED_API_BASE); direct URLs require host role and must match MUSIC_DIRECT_URL_HOSTS allowlist
  • Client-side auto-ducking to 35% volume while another participant is speaking
  • 30-second slow-mode throttle per attendee; reservation is placed before the async resolver so concurrent requests can't double-fire
  • Revision counter on Room incremented by stop, permission change, and track change; pending /play requests reject if the revision changed during the lookup

Confidence Score: 3.5 / 5

The security posture is solid and all three previously flagged P1 race conditions are correctly addressed. Score is held back by a likely functional break in Piped music search and a multi-instance gap in the MoM rate limiter.


Issues & Bugs

# Issue Location Severity Status
1 Stale host token keeps write access — 12h join-token could be replayed by a removed host finalize/route.ts L99-104 P1 ✅ Fixed — token is now a 60s purpose-scoped mom:finalize JWT issued only to live admins
2 Concurrent /play bypasses slow mode — two requests could both pass the 30s check before either resolver finished chatHandlers.ts L1040-1057 P1 ✅ Fixed — slow-mode reservation is set before await resolveMusicTrack, blocking the second concurrent request
3 Pending /play reverses host stop — inflight request could install a track after a host stopped music chatHandlers.ts L1060-1072 P1 ✅ Fixed — musicRevision counter is checked post-await; stop/permission changes bump it
4 Piped search response format mismatchresolveMusicTrack does Array.isArray(results) ? results : [], but Piped /search returns { items: [...], nextpage: "..." }, so list is always [] and search always returns "No music result found." chatHandlers.ts resolveMusicTrack P2 ⚠️ Pending — Piped search is effectively dead code as written
5 In-memory rate limit is process-local — the rateLimit Map in the Next.js route is not shared across instances/workers; in multi-instance deployments each node tracks its own counter, multiplying the effective limit finalize/route.ts L10-40 P3 ⚠️ Pending — low impact in single-instance setups, gap in horizontally scaled deployments
6 GitHub 4xx errors mapped to HTTP 502response.status >= 400 && response.status < 500 ? 502 : 503 returns 502 (Bad Gateway) for GitHub 401/403/404, which is semantically misleading finalize/route.ts L170-174 P3 ⚠️ Pending — cosmetic/misleading but not a security issue
7 isHost/isAdmin JWT fields declared but never checkedRoomAuthPayload declares these fields, but the route only validates purpose, roomId, and email; unused fields are dead weight and potentially confusing finalize/route.ts L12-19 P4 ⚠️ Pending — cosmetic
8 Web lint/typecheck unverifiedpnpm install blocked by registry timeouts for dashjs, next, @next/swc-win32-x64-msvc; full web-layer typecheck has not been run CI/local P3 ⚠️ Pending — infrastructure blocker

The most actionable pending item is issue #4: fixing resolveMusicTrack to destructure results.items instead of treating the Piped response as a top-level array will make music search actually functional.

Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.

@darkside4x

Copy link
Copy Markdown
Contributor Author

Follow-up fixes pushed in fix(meet): handle piped music search payloads:

  • resolveMusicTrack now supports Piped /search payloads shaped as { items: [...] } as well as bare arrays, so search playback is functional against normal Piped instances.
  • Removed unused isHost / isAdmin fields from the MoM finalize JWT payload type.
  • Replaced the previous GitHub 4xx -> 502 mapping with a small status mapper: conflicts stay 409, validation maps to 400, rate-limit maps to 429, upstream/server errors map to 503, and other dependency failures map to 424.

Remaining known limitation: MoM rate limiting is still in-memory/process-local. I did not add a new distributed limiter here because the web app does not already have a shared limiter for this route, and adding a production binding would be a separate infra change.

Comment thread apps/web/src/app/api/conclave/mom/finalize/route.ts
@darkside4x

Copy link
Copy Markdown
Contributor Author

@greptile Please provide a complete summary of the full updated latest PR, along with a confidence score out of 5. Additionally, list any issues or bugs, noting their severity and whether they are fixed or pending, in a tabular format.y are fixed or pending, in a tabular format.

@greptile-apps

greptile-apps Bot commented Jul 12, 2026

Copy link
Copy Markdown

PR #195feat(meet): add mom versioning and room music

Branch: darkside4x:ds4x/mom-music-systemACM-VIT:main
Status: Open | +1061 / −14 lines across 19 files | 3 commits | Last commit: 35d1fdc


Summary

This PR introduces two major subsystems to the Conclave real-time meetings platform:

1. MoM (Minutes of Meeting) Versioning

  • Adds a /api/conclave/mom/finalize Next.js route that accepts structured meeting minutes and commits them to a configured GitHub repository.
  • Authorization uses a two-layer scheme: a valid auth() session (host/admin) plus a short-lived (60s) room-bound JWT issued by the SFU (adminHandlers.ts).
  • Path segments are sanitized before writing. Payload is size-capped at 512 KB. Rate-limited to 4 requests per minute per user.
  • Required env vars: MOM_GITHUB_TOKEN, MOM_GITHUB_REPOSITORY. Optional: MOM_GITHUB_BRANCH (default: main), MOM_GITHUB_BASE_PATH (default: meeting-minutes).

2. Room Music System

  • Adds three permission levels in Room.ts: off, hosts, everyone.
  • Hosts can configure permissions and issue a /play <query|url> chat command.
  • Supports two resolution backends: Piped search (via MUSIC_PIPED_API_BASE) and direct HTTPS URLs from an allowlist (MUSIC_DIRECT_URL_HOSTS, hosts-only).
  • A slow-mode guard enforces a 30-second cooldown between /play requests per attendee.
  • Music state (track, position, permissions) is synchronized across SFU and web client.
  • The web client auto-ducks music to 35% volume when any other participant is speaking.
  • /play in DMs stays private and does not trigger room-wide music.

Key Files Changed

File Role
apps/web/src/app/api/conclave/mom/finalize/route.ts New — MoM GitHub commit route
packages/sfu/server/socket/handlers/adminHandlers.ts MoM token issuance, music permission controls
packages/sfu/server/socket/handlers/chatHandlers.ts /play resolution, slow-mode guard, stale-request rejection
packages/sfu/config/classes/Room.ts Music state, track, revision, request timing

Confidence Score: 4 / 5

The music-side race conditions (slow mode bypass, stale-request restart) were caught and resolved. One security issue on the MoM finalize path remains open.


Issues & Bugs

# Issue File Severity Status
1 Stale Host Token Keeps Write Access — A 12-hour SFU join token can be replayed after the host leaves or loses privileges. The finalize route never verifies current room membership or role. finalize/route.ts:99–104 P1 — Security ✅ Resolved (thread closed)
2 Concurrent /play Requests Bypass Slow Mode — Two requests from the same attendee can both pass the slow-mode check before either lookup finishes, causing the second to silently replace the first. chatHandlers.ts:1056–1064 P1 — Logic ✅ Resolved (thread closed)
3 Pending /play Request Reverses Host Stop — A /play request in-flight during a host stop action passes post-lookup permission checks (stopping doesn't revoke permission level), so music restarts after the explicit stop. chatHandlers.ts:1056–1064 P1 — Logic ✅ Resolved (thread closed)
4 Revoked Host Token Remains Valid (60s window) — The finalize token issued by the SFU has a 60-second TTL. If a host loses authority within that window, the route still accepts the token and performs the GitHub write because it never re-checks current room authority at request time. finalize/route.ts:107–111 P1 — Security Pending (thread open)

Issue #4 is the blocking item before merge. The fix is to make an SFU room-state call (or consult an in-memory room registry accessible to the web server) to verify the submitting user still holds host/admin authority at the time the finalize request arrives, rather than relying solely on the short-lived JWT claim.

@greptile-apps

greptile-apps Bot commented Jul 12, 2026

Copy link
Copy Markdown

PR Summary — feat(meet): add mom versioning and room music

Status: Open | Commits: 3 | Files changed: 19 | Lines: +1061 / -14


What Changed

MoM (Minutes of Meeting) Versioning

  • New POST /api/conclave/mom/finalize route writes markdown meeting minutes to a configured GitHub repository.
  • Requires both an active authenticated session and a short-lived finalizeToken JWT (issued by the SFU, scoped to purpose: "mom:finalize" and the host's email).
  • File path is date-stamped and room-scoped (meeting-minutes/YYYY-MM-DD-<roomId>.md). Existing files are updated via SHA lookup; new ones are created.
  • Rate limited to 4 finalizations per 60 seconds per user per room. Size capped at 512 KB.
  • Requires env vars: MOM_GITHUB_TOKEN, MOM_GITHUB_REPOSITORY. Optional: MOM_GITHUB_BRANCH, MOM_GITHUB_BASE_PATH.

Room Music System

  • New musicPermission field on Room: off | hosts | everyone.
  • /play <query or URL> chat command resolves a track via Piped API (MUSIC_PIPED_API_BASE) or an allowlisted HTTPS direct URL (MUSIC_DIRECT_URL_HOSTS, hosts-only).
  • Slow-mode per user: 30-second cooldown between /play requests, with reservation set at entry to prevent the race window.
  • Stale-request rejection: if music is stopped or permissions change while a lookup is in flight, the result is discarded.
  • Shared room music player auto-ducks to 35% volume when another participant is speaking.
  • /play in DMs stays private and does not trigger room-wide playback.
  • Host settings panel exposes music permission controls.
  • Music state is synced across all clients via SFU socket events.

Key Files

File Role
apps/web/src/app/api/conclave/mom/finalize/route.ts MoM GitHub write route
packages/sfu/server/socket/handlers/adminHandlers.ts Host music controls + MoM token issuance
packages/sfu/server/socket/handlers/chatHandlers.ts /play resolution with slow-mode and stale-request guards
packages/sfu/config/classes/Room.ts Music state, permissions, revision tracking

Confidence Score: 4 / 5

The music system race guards and stale-request logic are well-handled after the follow-up fixes. The one blocking security issue on the MoM finalize route remains open and must be addressed before merge.


Issues / Bugs

# Issue Severity Location Status
1 Stale Host Token Keeps Write Access — The initial version of the finalize route trusted a 12-hour join token without checking live room membership. A removed host could replay the token and write MoM to GitHub. P1 — High finalize/route.ts:99-104 ✅ Resolved (commit 8a2abca)
2 Concurrent /play Requests Bypass Slow Mode — Two requests from the same attendee could both pass the slow-mode check before either lookup finished, letting both succeed back-to-back. P1 — High chatHandlers.ts:1056-1064 ✅ Resolved (commit 8a2abca)
3 Pending /play Reverses Host Music Stop — An in-flight /play resolver result could reinstall a track after the host had already stopped music, because stopping didn't cancel pending requests. P1 — High chatHandlers.ts:1056-1064 ✅ Resolved (commit 8a2abca)
4 Revoked Host Token Remains Valid — The finalize route validates roomId, purpose, and session email from the JWT but never queries the SFU for current room authority. A host who loses privileges can still use a token issued before revocation (up to 60s TTL) to write meeting minutes to GitHub. P1 — High finalize/route.ts:107-111 Pending (open inline thread)

Issue 4 is the only blocker. The fix requires the finalize route to make a live authority check against the SFU (e.g., an internal /room/:id/is-host?email= endpoint, or embedding a short-TTL one-use nonce in the token that the SFU marks as consumed on issue).

@darkside4x

Copy link
Copy Markdown
Contributor Author

Addressed the remaining P1 in fix(meet): require live mom finalize authority:

  • mom:authorizeFinalize now creates a one-use authorization id in the live SFU Room and embeds it as the JWT jti along with the room clientId.
  • The Next finalize route no longer treats the JWT alone as sufficient. After validating the session + JWT, it calls the SFU admin endpoint /admin/rooms/:roomId/mom/finalize-authority across the configured SFU pool.
  • The SFU consumes the one-use authorization only if it exists, is unexpired, matches the email, and that email still maps to an active non-observer Admin client in the room.
  • If the host is removed/revoked after token issue, the live SFU check fails and the GitHub write is never attempted. Replays also fail because the authorization id is consumed once.

Validation repeated:

  • git diff --check
  • focused ESLint on touched SFU files: Room.ts, adminHandlers.ts, createApp.ts, chatHandlers.ts

Web lint remains blocked locally by the incomplete dependency install (eslint-plugin-react-hooks missing after pnpm registry timeouts).

Comment thread packages/sfu/config/classes/Room.ts
@darkside4x

Copy link
Copy Markdown
Contributor Author

@greptile Please provide a complete summary of the full updated latest PR, along with a confidence score out of 5. Additionally, list any issues or bugs, noting their severity and whether they are fixed or pending, in a tabular format.y are fixed or pending, in a tabular format.

@greptile-apps

greptile-apps Bot commented Jul 12, 2026

Copy link
Copy Markdown

PR #195 — Complete Updated Summary

feat(meet): add mom versioning and room music
Branch: darkside4x:ds4x/mom-music-systemACM-VIT:main
Status: Open | 4 commits | 20 files | +1,202 / −14 lines
Last commit: dcd12eebfix(meet): require live mom finalize authority


What This PR Does

1. MoM (Minutes of Meeting) Versioning

  • New POST /api/conclave/mom/finalize Next.js route writes markdown meeting minutes as versioned files to a configured GitHub repository.
  • Three-layer auth: active auth() session + a 60s purpose-scoped mom:finalize JWT (issued by the SFU admin socket) + a live one-use authorizationId stored in the SFU Room, consumed server-side via /admin/rooms/:roomId/mom/finalize-authority before any GitHub write.
  • File path is date-stamped and room-scoped (YYYY-MM-DD-<roomId>.md). Existing files are updated via SHA lookup.
  • Rate-limited at 4 calls/minute per user per room; payload capped at 512 KB.
  • Required env: MOM_GITHUB_TOKEN, MOM_GITHUB_REPOSITORY. Optional: MOM_GITHUB_BRANCH, MOM_GITHUB_BASE_PATH.

2. Room Music System

  • Three permission levels on Room: off | hosts | everyone.
  • /play <query or URL> chat command; silently skipped inside DMs.
  • Piped API backend for search (MUSIC_PIPED_API_BASE); direct HTTPS URLs require host role and must match the MUSIC_DIRECT_URL_HOSTS allowlist.
  • 30-second slow-mode per attendee with reservation placed before the async resolver to close the concurrency window.
  • musicRevision counter incremented on stop, permission change, or track change — stale in-flight requests are discarded post-await.
  • Client-side auto-ducking to 35% volume while another participant is speaking.
  • Host settings panel exposes permission controls; state synced to all clients via SFU socket events.

Confidence Score: 4.5 / 5

All four P1 issues have been addressed in code. The one remaining inline thread (Transferred Host Retains Write Authority) is still formally unresolved on GitHub but the latest commit's live SFU authority check (consumeMomFinalizeAuthorization validates the email still maps to an active non-observer Admin in the room) directly closes the gap. Score is held back only by the process-local rate limiter and the unverified web lint pipeline.


Issues & Bugs

# Issue Location Severity Status
1 Stale Host Token Keeps Write Access — 12h join token could be replayed by a removed host finalize/route.ts:99–104 P1 — Security ✅ Fixed — token replaced by 60s purpose-scoped mom:finalize JWT issued only to live admins
2 Concurrent /play Requests Bypass Slow Mode — two requests from the same attendee could both pass the 30s check before either lookup finished chatHandlers.ts:1056–1064 P1 — Logic ✅ Fixed — slow-mode reservation set before await resolveMusicTrack
3 Pending /play Reverses Host Stop — inflight request could reinstall a track after a host stopped music chatHandlers.ts:1056–1064 P1 — Logic ✅ Fixed — musicRevision checked post-await; stop/permission changes bump it
4 Revoked Host Token Remains Valid (60s window) — finalize route checked JWT claims but not live room authority finalize/route.ts:107–111 P1 — Security ✅ Fixed — route now calls SFU /admin/rooms/:roomId/mom/finalize-authority; one-use authorization consumed only if email still maps to an active Admin
5 Transferred Host Retains Write Authority — former host remained an Admin client and could still obtain/consume a finalization token after losing host ownership Room.ts:1004 P1 — Security ⚠️ Addressed in code (live SFU check in consumeMomFinalizeAuthorization rejects non-current-hosts), but inline thread still open — awaiting formal resolution
6 Piped Search Response Format MismatchresolveMusicTrack treated Piped /search response as a bare array; actual shape is { items: [...] }, making search always return no results chatHandlers.ts P2 — Functional ✅ Fixed — results.items now correctly destructured
7 In-Memory Rate Limit Is Process-LocalrateLimit Map not shared across Next.js instances; effective limit multiplies by node count in horizontal deployments finalize/route.ts:10–40 P3 — Infra ⚠️ Pending — explicitly acknowledged as out of scope; no shared limiter in this route today
8 GitHub 4xx Errors Mapped to 502 — 401/403/404 from GitHub API returned as Bad Gateway finalize/route.ts:170–174 P3 — Cosmetic ✅ Fixed — status mapper added (409→409, 422→400, 429→429, 5xx→503, other→424)
9 Unused isHost/isAdmin JWT Fields — declared in RoomAuthPayload but never checked finalize/route.ts:12–19 P4 — Cosmetic ✅ Fixed — dead fields removed
10 Web Lint/Typecheck Unverifiedpnpm install blocked by registry timeouts for dashjs, next, @next/swc-win32-x64-msvc; no full web-layer typecheck run CI / local P3 — Process ⚠️ Pending — infrastructure blocker unrelated to logic

Only two items remain open: the formally-unresolved inline thread for issue #5 (the code fix is in place — the live SFU check rejects former hosts — the thread just needs to be marked resolved) and the known in-memory rate limiter gap (#7, acknowledged out of scope). Neither is a functional regression. The PR is effectively merge-ready pending thread resolution.

Comment thread packages/sfu/config/classes/Room.ts
@darkside4x

Copy link
Copy Markdown
Contributor Author

@greptile Please provide a complete summary of the full updated latest PR, along with a confidence score out of 5. Additionally, list any issues or bugs, noting their severity and whether they are fixed or pending, in a tabular format.y are fixed or pending, in a tabular format.

@greptile-apps

greptile-apps Bot commented Jul 12, 2026

Copy link
Copy Markdown

PR #195 Summary — feat(meet): add mom versioning and room music

Confidence Score: 4/5


Overview

This PR introduces two major features to the Conclave meetings platform across 20 files (+1,207 / -14 lines):

1. MoM (Minutes of Meeting) Versioning

  • Host/admin-only finalization endpoint (apps/web/src/app/api/conclave/mom/finalize/route.ts) that commits exported meeting minutes to a configured GitHub repository.
  • Authorization is double-gated: a valid Next-Auth session (host/admin only) and a short-lived (~60s), one-time-use SFU nonce token issued by the room's authority check.
  • In-process rate limiter: 4 requests per user per 60-second window.
  • Maximum payload: 512 KB. Path segments are sanitized before GitHub writes.
  • Configurable via MOM_GITHUB_TOKEN, MOM_GITHUB_REPOSITORY, with optional MOM_GITHUB_BRANCH and MOM_GITHUB_BASE_PATH.

2. Room Music System

  • Three permission levels: off, hosts, everyone, settable by the host from settings.
  • /play <query|url> chat command with Piped API search (MUSIC_PIPED_API_BASE) and allowlisted HTTPS direct URLs (MUSIC_DIRECT_URL_HOSTS, hosts only).
  • /play in DMs remains private and does not start room-wide music.
  • Shared player auto-ducks to 35% volume when another participant is speaking.
  • Pending /play requests re-check permissions before broadcasting.
  • Slow-mode: 30-second per-user rate limit on /play requests.

Key Files Changed

File Role
apps/web/src/app/api/conclave/mom/finalize/route.ts New — GitHub versioning endpoint with auth, rate-limiting, nonce consumption
packages/sfu/config/classes/Room.ts Music state + MoM authority checks (hasActiveHostEmail, hostUserKey gating)
packages/sfu/server/socket/handlers/adminHandlers.ts Room music controls, MoM finalization token minting
packages/sfu/server/socket/handlers/chatHandlers.ts /play resolution with slow-mode, permission, and revision checks

Issues & Bugs

# Issue Severity File Status
1 Stale Host Token Keeps Write Access — A 12-hour join token could be replayed by a departed or demoted host; current room membership was never re-checked. P1 — Security mom/finalize/route.ts:99-104 ✅ Resolved
2 Concurrent Requests Bypass Slow Mode — Two simultaneous /play requests from the same user could both pass the 30-second slow-mode check before either async lookup completed. P1 — Logic / Abuse chatHandlers.ts:1056-1064 ✅ Resolved
3 Pending /play Reverses Music Stop — An in-flight /play awaiting resolver completion would re-install a track after the host had already stopped music, silently overriding the host action. P1 — Logic chatHandlers.ts:1056-1064 ✅ Resolved
4 Revoked Host Token Remains Valid — Within the ~60-second nonce window, a host who lost host status could still consume the nonce and write MoM to GitHub, because current room authority was not rechecked at consumption time. P1 — Security mom/finalize/route.ts:107-111 ✅ Resolved
5 Transferred Host Retains Write Authority — After an explicit host transfer, the former host's client remained Admin, so hasActiveHostEmail() accepted their email and they could still mint and consume a finalization nonce. Verified by T-Rex harness. P1 — Security Room.ts:1004 ✅ Resolved (commit bab13864)
6 Promoted Host Fails Authority Check — When the original host disconnects and a participant is auto-promoted, hostUserKey is not updated to the new host's email. The promoted host is then rejected by hasActiveHostEmail() and cannot obtain a MoM finalization token. Verified by T-Rex harness. P1 — Functional Blocker Room.ts:1000-1001 Pending — Not Fixed

Merge Readiness

The single remaining open issue (#6) is a functional blocker: in any meeting where the original host disconnects (a common scenario), the auto-promoted host will be unable to finalize meeting minutes at all. The disconnect-promotion path in Room.ts needs to call this.hostUserKey = <promoted client's email> (or equivalent) when it broadcasts the hostChanged event. All other P1 issues have been addressed.

@darkside4x

Copy link
Copy Markdown
Contributor Author

Fixed the auto-promotion blocker in fix(meet): sync host owner on auto promotion:

  • Both auto-promotion paths now update room.hostUserKey to the promoted client's user key.
  • This keeps hostChanged, getHostUserId(), and MoM hasActiveHostEmail() authority aligned after the original host disconnects or is removed.
  • A promoted host can now mint/consume MoM finalize authority; a transferred-away former host remains blocked by the current-host check.

Validation repeated:

  • git diff --check
  • focused ESLint on disconnectHandlers.ts, controlPlane.ts, Room.ts, and adminHandlers.ts

@darkside4x

Copy link
Copy Markdown
Contributor Author

@greptile Please provide a complete summary of the full updated latest PR, along with a confidence score out of 5. Additionally, list any issues or bugs, noting their severity and whether they are fixed or pending, in a tabular format.y are fixed or pending, in a tabular format.

@greptile-apps

greptile-apps Bot commented Jul 12, 2026

Copy link
Copy Markdown

PR #195 — Complete Final Summary

feat(meet): add mom versioning and room music
Status: Open | 6 commits | 21 files | +1,209 / −14 lines
Last commit: 0e545a03fix(meet): sync host owner on auto promotion


What This PR Does

1. MoM (Minutes of Meeting) Versioning

  • New POST /api/conclave/mom/finalize route writes Markdown meeting minutes as versioned files to a configured GitHub repository.
  • Three-layer auth: active auth() session + a 60s purpose-scoped mom:finalize JWT (issued by the SFU admin socket) + a live one-use authorizationId stored in the SFU Room and consumed server-side via /admin/rooms/:roomId/mom/finalize-authority before any GitHub write.
  • MoM authorization checks the requesting email against the current hostUserKey — not merely any Admin client — so transferred and revoked hosts are blocked at both token mint and consume time.
  • Auto-promotion paths (disconnectHandlers, controlPlane) now update room.hostUserKey to the promoted client's key, keeping getHostUserId() and hasActiveHostEmail() aligned.
  • Rate-limited: 4 calls/minute per user per room. Payload capped at 512 KB. Path segments sanitized.
  • Required env: MOM_GITHUB_TOKEN, MOM_GITHUB_REPOSITORY. Optional: MOM_GITHUB_BRANCH, MOM_GITHUB_BASE_PATH.

2. Room Music System

  • Three permission levels on Room: off | hosts | everyone.
  • /play <query|url> chat command; silently skipped inside DMs.
  • Piped API backend for search (MUSIC_PIPED_API_BASE); direct HTTPS URLs require host role and must match MUSIC_DIRECT_URL_HOSTS allowlist. Response shape { items: [...] } is correctly destructured.
  • 30-second slow-mode per attendee, with reservation placed before the async resolver to close the concurrency window.
  • musicRevision counter incremented on stop, permission change, or track change — stale in-flight requests are discarded post-await.
  • Client auto-ducks to 35% volume while another participant is speaking.
  • Host settings panel exposes permission controls; state synced to all clients via SFU socket events.

Confidence Score: 5 / 5

All six P1 issues identified during review have been fixed in code, and all inline review threads are marked resolved. The two remaining open items (process-local rate limiter, unverified web lint) are P3 quality/infra concerns acknowledged by the author as out of scope for this PR. No blocking issues remain.


Issues & Bugs

# Issue Location Severity Status
1 Stale Host Token Keeps Write Access — 12h join token could be replayed by a removed host; current room membership never checked finalize/route.ts:99–104 P1 — Security ✅ Fixed (8a2abca) — replaced by 60s purpose-scoped JWT issued only to live admins
2 Concurrent /play Requests Bypass Slow Mode — two requests from the same attendee could both pass the 30s check before either lookup finished chatHandlers.ts:1056–1064 P1 — Logic ✅ Fixed (8a2abca) — slow-mode reservation set before await resolveMusicTrack
3 Pending /play Reverses Host Stop — inflight request could reinstall a track after a host stopped music chatHandlers.ts:1056–1064 P1 — Logic ✅ Fixed (8a2abca) — musicRevision checked post-await; stop/permission changes bump it
4 Revoked Host Token Remains Valid (60s window) — finalize route checked JWT claims but not live room authority at request time finalize/route.ts:107–111 P1 — Security ✅ Fixed (dcd12eeb) — route calls SFU /admin/rooms/:roomId/mom/finalize-authority; one-use nonce consumed only if email still maps to an active current-host Admin
5 Transferred Host Retains Write Authority — former host remained Admin after transfer and could still mint/consume a finalization token Room.ts:1004 P1 — Security ✅ Fixed (bab13864) — authorization now requires email to match room.hostUserKey, not merely any active Admin
6 Promoted Host Fails Authority Check — auto-promotion on disconnect did not update hostUserKey, so promoted host was rejected by hasActiveHostEmail() Room.ts:1000–1001 P1 — Functional ✅ Fixed (0e545a03) — both auto-promotion paths now set room.hostUserKey to the promoted client's key
7 Piped Search Response Format MismatchresolveMusicTrack treated Piped /search response as a bare array; actual shape is { items: [...] }, making search always return no results chatHandlers.ts P2 — Functional ✅ Fixed — results.items correctly destructured
8 GitHub 4xx Errors Mapped to 502 — 401/403/404 from GitHub API returned as Bad Gateway, misleading callers finalize/route.ts:170–174 P3 — Cosmetic ✅ Fixed — status mapper added (409→409, 422→400, 429→429, 5xx→503, other→424)
9 Unused isHost/isAdmin JWT Fields — declared in RoomAuthPayload but never checked finalize/route.ts:12–19 P4 — Cosmetic ✅ Fixed — dead fields removed
10 In-Memory Rate Limit Is Process-LocalrateLimit Map not shared across Next.js instances; effective limit multiplied by node count in horizontal deployments finalize/route.ts:10–40 P3 — Infra ⚠️ Pending — explicitly acknowledged out of scope; no shared limiter exists for this route today
11 Web Lint/Typecheck Unverifiedpnpm install blocked by registry timeouts for dashjs, next, @next/swc-win32-x64-msvc; full web-layer typecheck has not been run CI / local P3 — Process ⚠️ Pending — infrastructure blocker unrelated to logic

All P1s are resolved. The two open items are P3 and non-blocking for merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant