Skip to content

feat(sync): make the WebRTC room password reachable from the UI - #777

Merged
d-oit merged 6 commits into
mainfrom
feat/sync-room-password
Sep 11, 2026
Merged

feat(sync): make the WebRTC room password reachable from the UI#777
d-oit merged 6 commits into
mainfrom
feat/sync-room-password

Conversation

@d-oit

@d-oit d-oit commented Sep 11, 2026

Copy link
Copy Markdown
Owner

Makes the encrypted-sync control from Plan 134 actually usable. Tracked as Plan 136 (plans/136-sync-room-password.md).

Problem

Plan 134 added password?: string to joinRoom's options, which y-webrtc uses to derive an AES-GCM key for the signaling and data channels. That landed at the API boundary only — the sole production caller invoked joinRoom(id) with no options, and no UI existed to set a password. The encryption could never be switched on. (Reported as a P2 finding during the pre-merge review of #776.)

Change

  • Adds a masked, labelled Room password field to the disconnected panel, threaded through SyncStatusCard to SyncView and forwarded on join.
  • A blank field calls joinRoom(id) with a single argument, so the unencrypted path stays byte-for-byte unchanged.
  • The secret stays in component state only: never logged, never written to the sync event history, never persisted or synced, and cleared on both join and leave.
  • Help text states that both peers need the same password and that a mismatch cannot be signalled (the room simply will not decrypt), since y-webrtc cannot report it as an auth error.

Tests

7 new tests across sync-view.test.tsx and sync-helpers.test.tsx: masked rendering, change forwarding, aria-describedby linkage, Enter-to-join, the password reaching joinRoom, the single-argument unencrypted path, and an assertion that the password never appears in the sync history.

Review note: passing undefined as an explicit second argument broke 11 pre-existing assertions in sync-view-coverage.test.tsx (toHaveBeenCalledWith('room-123') does not match ('room-123', undefined)). Rather than loosen those assertions, the implementation branches to a single-argument call when no password is set.

Verification

  • pnpm run lint, pnpm run typecheck, pnpm run build all clean.
  • pnpm run test: 159 files, 2374 passed, 1 pre-existing documented skip.
  • sync-helpers.tsx 424 LOC / sync-view.tsx 298 LOC — both under the 500 limit.

🤖 Generated with Codebuff


📝 Summary by GitNexus

Summary

This appears to be a concentrated React UI change for exposing WebRTC room password access within the studio sync views. The graph marks the overall blast radius as critical, with impact centered on sync view behavior and its supporting UI components.

🔴 CRITICAL blast radius. A frontend change to the studio sync UI in src/components/studio/views/sync-view.tsx and src/components/studio/views/sync-helpers.tsx, reaching two direct dependents.

Most of the change is concentrated in src/components/studio/views/sync-view.tsx, including SyncView, entities, claims, addEvent, and the sync lifecycle handlers handlePeers, handleJoin, handleLeave, handleResync, handleConflictResolve, handleConflictDismiss, and handleQrScan. Review the interactions among these handlers first, since this file carries 11 changed symbols and sits on 18 affected flows.

The impact lands across the human-named Views and Sync modules. Supporting UI changes in src/components/studio/views/sync-helpers.tsx affect DisconnectedPanel and SyncStatusCard, with corresponding coverage updates in src/components/studio/views/sync-helpers.test.tsx and src/components/studio/views/sync-view.test.tsx.

Added by GitNexus for PR #777. Edit freely — this block is replaced on the next review, everything above it is left untouched.

Plan 134 added `password` to `joinRoom`'s options, but the only production
caller passed none and no UI existed to set one — so the AES-GCM encryption
y-webrtc derives from that password could never actually be switched on.

Adds a masked, labelled room-password field to the disconnected panel, threaded
through SyncStatusCard to SyncView and forwarded on join. A blank field calls
`joinRoom(id)` with a single argument so the unencrypted path stays byte-for-byte
unchanged. The secret is held in component state only: never logged, never added
to the sync event history, never persisted, and cleared on join and on leave.

🧪 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
do-knowledge-studio Ready Ready Preview, v0 Sep 11, 2026 11:51am UTC

@github-actions github-actions Bot added the documentation Documentation improvements label Sep 11, 2026
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Blocked merge diagnosis — blocked
⏳ Check run(s) still in progress: ["Codacy Static Code Analysis","Detect Changes","Diagnose Blocked Merge State","Secret Detection","Shell Script Security Analysis","Infrastructure as Code Security","Trivy Filesystem Security Scan","commitlint","Analyze (javascript-typescript)","Analyze (actions)"]

@codacy-production

codacy-production Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 9 complexity · 1 duplication

Metric Results
Complexity 9
Duplication 1

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@gitnexus-check

gitnexus-check Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor
Akon Labs

GitNexus Review · PR #777

No issues found in 5 changed files.

🤖 Agent context — 14 symbols · 5 files

Summary

This appears to be a concentrated React UI change for exposing WebRTC room password access within the studio sync views. The graph marks the overall blast radius as critical, with impact centered on sync view behavior and its supporting UI components.

🔴 CRITICAL blast radius. A frontend change to the studio sync UI in src/components/studio/views/sync-view.tsx and src/components/studio/views/sync-helpers.tsx, reaching two direct dependents.

Most of the change is concentrated in src/components/studio/views/sync-view.tsx, including SyncView, entities, claims, addEvent, and the sync lifecycle handlers handlePeers, handleJoin, handleLeave, handleResync, handleConflictResolve, handleConflictDismiss, and handleQrScan. Review the interactions among these handlers first, since this file carries 11 changed symbols and sits on 18 affected flows.

The impact lands across the human-named Views and Sync modules. Supporting UI changes in src/components/studio/views/sync-helpers.tsx affect DisconnectedPanel and SyncStatusCard, with corresponding coverage updates in src/components/studio/views/sync-helpers.test.tsx and src/components/studio/views/sync-view.test.tsx.

🔴 CRITICAL blast radius — this change reaches 2 downstream symbols across 2 modules; this lands on a critical surface, so review the dependents carefully before merging.

Blast Level Dependents Modules Files
🔴 CRITICAL 2 2 5

What changed

Symbol Changes (14)
Kind Symbol Location
Const defaultProps src/components/studio/views/sync-helpers.test.tsx:16
Function DisconnectedPanel src/components/studio/views/sync-helpers.tsx:253
Function SyncStatusCard src/components/studio/views/sync-helpers.tsx:304
Function SyncView src/components/studio/views/sync-view.tsx:44
Function entities src/components/studio/views/sync-view.tsx:45
Function claims src/components/studio/views/sync-view.tsx:46
Function addEvent src/components/studio/views/sync-view.tsx:60
Function handlePeers src/components/studio/views/sync-view.tsx:97
Function handleJoin src/components/studio/views/sync-view.tsx:121
Function handleLeave src/components/studio/views/sync-view.tsx:142
Function handleResync src/components/studio/views/sync-view.tsx:153
Function handleConflictResolve src/components/studio/views/sync-view.tsx:166
Function handleConflictDismiss src/components/studio/views/sync-view.tsx:174
Function handleQrScan src/components/studio/views/sync-view.tsx:178
Changed Files (5)
File Status
plans/136-sync-room-password.md 🟢 added
src/components/studio/views/sync-helpers.test.tsx 🟡 modified
src/components/studio/views/sync-helpers.tsx 🟡 modified
src/components/studio/views/sync-view.test.tsx 🟡 modified
src/components/studio/views/sync-view.tsx 🟡 modified

What it affects

Architecture Impact

Module Hits Direct
Views 7 🟢
Sync 3

Blast Radius

Depth Count
d1 (direct) 2
d2 (indirect) 0
d3 (transitive) 0
Direct dependents (d1)
  • src/components/studio/views/sync-view.tsx:87 · handleStatus
  • src/components/studio/views/sync-view.tsx:80 · handleSynced

What to check

File Risk (1)
File Risk Category
plans/136-sync-room-password.md 🟢 LOW Documentation

🔀 Structural changes · feat/sync-room-passwordmain

Both branches are separately indexed, so this compares their code graphs directly — what the diff cannot show.

Symbols added (8)

  • src/components/studio/views/sync-view.tsx::ConflictSection
  • src/components/studio/views/sync-view.tsx::OnlineUsersCard
  • src/components/studio/views/sync-view.tsx::SyncHeader
  • src/components/studio/views/sync-view.tsx::SyncHistoryCard
  • src/components/studio/views/sync-view.tsx::SyncProviderEventHandlers
  • src/components/studio/views/sync-view.tsx::eventDotClass
  • src/components/studio/views/sync-view.tsx::useRoomDiscovery
  • src/components/studio/views/sync-view.tsx::useSyncProviderEvents

Full detail lives in the GitNexus check run for this commit.

@deepsource-io

deepsource-io Bot commented Sep 11, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in 9b88f25...14d6784 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
JavaScript Sep 11, 2026 11:50a.m. Review ↗
Python Sep 11, 2026 11:50a.m. Review ↗
Shell Sep 11, 2026 11:50a.m. Review ↗
SQL Sep 11, 2026 11:50a.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

…-0067

DeepSource's JavaScript analyzer failed this branch on JS-0067: a top-level
`export function` is read as a global-scope declaration. The `.deepsource.toml`
skip does not suppress findings on new code (LESSON-031), so the fix is at code
level, using the repo's `const fn = () => {}` convention. No behaviour change —
the export stays a named export consumed identically.

🧪 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
Comment thread src/components/studio/views/sync-view.tsx Outdated
@gitnexus-check

Copy link
Copy Markdown
Contributor

🔄 What's new in this push (35a0853)

The newest push appears focused on UI changes in src/components/studio/views/sync-view.tsx, touching SyncView, entities, claims, handleJoin, handleLeave, and handleResync. There are no newly reached modules and no risk transition.

The main GitNexus review comment has the full, updated report.

Two further DeepSource findings on the file this branch touches:

- JS-R1005: SyncView measured a cyclomatic complexity of 8. The provider-event
  and LAN-discovery effects move into `useSyncProviderEvents` and
  `useRoomDiscovery`; both accept only stable setters/useCallback, so the
  subscriptions are still established exactly once and behaviour is unchanged.
- JS-0116: `handleJoin` was `async` with no `await` anywhere. It is now a plain
  callback passed straight to `onJoin`.

Fixed at code level rather than with suppression comments.

🧪 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
@gitnexus-check

Copy link
Copy Markdown
Contributor

🔄 What's new in this push (96369fd)

The newest push appears focused on UI and synchronization behavior in src/components/studio/views/sync-view.tsx, updating 11 functions including SyncView, entities, claims, addEvent, handlePeers, handleJoin, handleLeave, handleResync, handleConflictResolve, and handleConflictDismiss. No newly reached modules or risk transition are reported.

The main GitNexus review comment has the full, updated report.

Comment thread src/components/studio/views/sync-view.tsx Outdated
Comment thread src/components/studio/views/sync-view.tsx
DeepSource still sized SyncView at complexity 8 after the effect extraction,
because the driver is JSX branching rather than the effects. The header, conflict
card, sync-history card, and online-users card move into named components, and
the per-event colour chain becomes an exhaustive switch helper. Only the room-id
fallback and the error-message ternary remain in the component body.

Also braces the `stopDiscovery` cleanup body: DeepSource JS-0045 reads the
one-line `() => { stopDiscovery() }` form as returning a value.

🧪 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
@gitnexus-check

Copy link
Copy Markdown
Contributor

🔄 What's new in this push (a5468d3)

The newest push appears to update the studio sync UI in src/components/studio/views/sync-view.tsx, touching SyncView, entities, claims, addEvent, handlePeers, handleJoin, handleLeave, handleResync, handleConflictResolve, and handleConflictDismiss, plus 1 more function. No newly reached modules or risk transition are reported.

The main GitNexus review comment has the full, updated report.

… default

DeepSource JS-0045 objected to the wrapped cleanup arrow, so the hook now returns
`stopDiscovery` itself — it already takes no arguments and returns void, so it is
a valid cleanup as-is. JS-0047/JS-0045 also wanted the exhaustive event-colour
switch to carry a default arm.

🧪 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
Comment thread src/components/studio/views/sync-view.tsx Outdated
Comment thread src/components/studio/views/sync-view.tsx
Comment thread src/components/studio/views/sync-view.tsx
@gitnexus-check

Copy link
Copy Markdown
Contributor

🔄 What's new in this push (06553ae)

The newest push appears focused on the studio sync UI in src/components/studio/views/sync-view.tsx, changing SyncView, entities, claims, addEvent, and peer, join, leave, resync, and conflict handlers including handlePeers, handleJoin, handleLeave, handleResync, handleConflictResolve, and handleConflictDismiss. 11 symbols changed in total, with no newly reached modules and no risk transition.

The main GitNexus review comment has the full, updated report.

Comment thread src/components/studio/views/sync-view.tsx Outdated
DeepSource JS-0045 is a consistent-return rule: the early bare `return` mixed with
a cleanup return made the effect callback's return paths inconsistent. The guarded
branch form was previously accepted and keeps the behaviour identical.

🧪 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
@gitnexus-check

Copy link
Copy Markdown
Contributor

🔄 What's new in this push (14d6784)

The newest push appears to update UI sync handling in src/components/studio/views/sync-view.tsx, touching 11 functions including SyncView, entities, claims, addEvent, handlePeers, handleJoin, handleLeave, handleResync, handleConflictResolve, and handleConflictDismiss. No newly reached modules or risk transition are reported.

The main GitNexus review comment has the full, updated report.

@d-oit
d-oit merged commit 1bc3dc7 into main Sep 11, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

config documentation Documentation improvements tests Related to automated/manual tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant