Classroom join codes - #25
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e setup Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The IDE keeps polling /api/sim/status (and the editor proxy reconnects) until the page navigates, and any authenticated poll can restart the container Leave just stopped. POST /u/:slug/api/leave now signs out via Better Auth before stopping the workspace and forwards its cookie-clearing Set-Cookie headers; stop failures return a structured error. getSessionFromRequest also rejects a guest whose session row is gone, so the 5-minute cookie cache cannot keep a left guest signed in. The client only falls back to authClient.signOut() when the leave request fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…guests
The join endpoint read the guest before ensureWorkspace, so a guest whose
slug moved on allocation ("student" -> "student-1") got the old slug baked
into the cookie cache, and RootIndex sent them to another student's
workspace. Read the user after ensureWorkspace.
Better Auth's own GET /api/auth/get-session still reported a guest of an
ended classroom as signed in; the dispatcher now answers null (Better
Auth's no-session shape) whenever getSessionFromRequest rejects the
request, and passes through otherwise.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…join retirePreviousSession runs after Better Auth has created the new guest's session, so a docker stop failure there turned a successful join into a 500 without the session cookie. Log it and let the idle reaper catch up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Record that behind the Cloudflare Pages front the per-IP join bucket keys on a Cloudflare egress IP, with the CF-Connecting-IP + Caddy trusted_proxies follow-up, and list the four classroom audit actions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deleting a large classroom's guests can outlast the 60 s interval; a second pass would start cleaning the same classroom again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rver Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…leave - Decide rate-limit failures in one tick before the auth handler so a parallel burst of bad codes can't all pass the check. - Reserve guest slots synchronously so concurrent joins can't exceed the 60-guest cap. - Close a workspace's run/import/lesson-load/gamepad sockets when it is stopped (Leave, replaced guest) or its user is deleted (End now, sweeper). - Proxy /admin/classrooms in Vite dev. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A first-time student picking a lesson has no work to lose, so loading or importing into an empty project starts straight away. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Added classroom join codes: an admin starts a short-lived classroom (Admin → Classrooms) with a 6-digit code, and students join at
/joinwith just the code and their name — no OAuth, no allowlist. Guests and their projects are deleted automatically when the classroom ends.POST /api/auth/classroom/join) mints real sessions for guest users (user.classroomIdset, rolestudent); rejoin by the same name returns to the same workspace after a confirm step.getSessionFromRequestand on Better Auth'sget-session).ClassroomSweeper(60 s) and End now delete guests, workspaces and files via adeleteUserAndWorkspacehelper shared withDELETE /admin/users/:id.student).Known limitation: behind the Cloudflare Pages front the per-IP bucket collapses to one shared bucket — documented in 043 with the follow-up (forward
CF-Connecting-IP+ Caddytrusted_proxies).Validation: typecheck; 501 control-plane, 153 web, 78 E2E, 12 E2E security tests pass (one pre-existing Preview E2E test flaked once, 3/3 on rerun). Manual check of the admin Classrooms tab in a browser still pending.
🤖 Generated with Claude Code