Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2ddb567
feat(control): classroom storage, name/code helpers, join rate limiter
mathewdunne Sep 30, 2026
62f02d2
added spec docs
mathewdunne Sep 30, 2026
d74ffb6
fix(control): escape diacritics range in guestNameKey
mathewdunne Sep 30, 2026
fc2c610
feat(auth): classroom join plugin with rejoin-by-name guest users
mathewdunne Sep 30, 2026
55959ce
fix(control): random slug fallback and JOIN_FAILED for guest workspac…
mathewdunne Sep 30, 2026
cc3a0bd
feat(auth): guest sessions end when their classroom ends
mathewdunne Sep 30, 2026
3a9591b
feat(control): classroom join rate limit, session hand-off, /join route
mathewdunne Sep 30, 2026
4b92892
feat(control): admin classroom routes and expiry sweeper
mathewdunne Sep 30, 2026
93f2acd
feat(control): guest leave endpoint and classroom end time on session
mathewdunne Sep 30, 2026
84b7ea7
feat(web): join-a-classroom page
mathewdunne Sep 30, 2026
6ac7d92
feat(web): guest user menu with Leave
mathewdunne Sep 30, 2026
b798a4e
feat(admin): Classrooms tab
mathewdunne Sep 30, 2026
5dee42f
test(e2e): classroom join, leave, and rejoin
mathewdunne Sep 30, 2026
a4e9ff7
docs: classroom join codes (decision 043)
mathewdunne Sep 30, 2026
3238a8e
fix(classroom): Leave ends the browser session server-side
mathewdunne Sep 30, 2026
bd9885e
fix(classroom): fresh slug in the cookie cache; gate get-session for …
mathewdunne Sep 30, 2026
9e0065d
fix(classroom): a failed stop of the previous guest doesn't fail the …
mathewdunne Sep 30, 2026
9677fe9
docs(classroom): per-IP limit behind Cloudflare; classroom audit actions
mathewdunne Sep 30, 2026
27ea709
fix(classroom): skip overlapping classroom sweeps
mathewdunne Sep 30, 2026
38134fc
fix(admin): show an error when Start/End classroom can't reach the se…
mathewdunne Sep 30, 2026
e7445c9
chore: refresh graphify graph after classroom fixes
mathewdunne Sep 30, 2026
691ff91
review feedback fix
mathewdunne Sep 30, 2026
a3b4f1e
fix(classroom): hold join limits under concurrency; close sockets on …
mathewdunne Oct 1, 2026
620b626
docs(classroom): spell out the Cloudflare per-IP limit follow-up
mathewdunne Oct 1, 2026
e607eca
chore(biome): ignore the .impeccable plugin cache
mathewdunne Oct 1, 2026
fb6451f
graphify
mathewdunne Oct 1, 2026
5a67e91
fix(web): skip the discard prompt when the workspace is empty
mathewdunne Oct 1, 2026
708e500
graphify
mathewdunne Oct 1, 2026
305330a
docs update
mathewdunne Oct 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ from `showDriverStation` to make that possible. See
`docs/decisions/041-project-preview.md` and
[`docs/using-coderunner.md`](./docs/using-coderunner.md).

**Classroom join codes (post-V2):** admins start a short-lived classroom
(Admin → Classrooms) with a 6-digit code; students join at `/join` with the
code and their name and become guest users (`user.classroomId` set, role
`student`, no allowlist). A custom Better Auth plugin
(`auth/classroom-plugin.ts`) mints the session; `app/classroom-routes.ts`
rate-limits failed attempts and retires the browser's previous guest
session. Guest sessions die with the classroom (checked in
`getSessionFromRequest`), guests have a **Leave** button that stops their
container, and `ClassroomSweeper` deletes guests of ended/expired
classrooms. See `docs/decisions/043-classroom-join-codes.md`.

**Containerized control plane (post-V2):** the control plane ships as a Docker
image (`containers/control/Dockerfile` → `ghcr.io/mathewdunne/coderunner-control`)
and is deployed with docker compose (`docker-compose.yml` base +
Expand Down Expand Up @@ -134,7 +145,7 @@ arch-independent). See `docs/decisions/035-multi-arch-images-and-workflow-split.
## Key References

- `docs/` + `website/` — docs site content and Docusaurus config; published at `https://mathewdunne.github.io/CodeRunner/`; run `bun run docs:dev` to browse locally, `bun run docs:build` to build.
- `docs/decisions/` — all architecture decision logs (011–041 active; 001–010 archived under `docs/decisions/archive/`).
- `docs/decisions/` — all architecture decision logs (011–043 active; 001–010 archived under `docs/decisions/archive/`).
- Pinned AdvantageScope submodule: `vendor/AdvantageScope` at tag `v26.0.2`.

## Commands
Expand Down
17 changes: 17 additions & 0 deletions apps/control/migrations/012_classrooms.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- Classroom join codes (decision 043). Guest users point at a classroom via
-- the Better Auth user.classroomId column, which Better Auth itself adds
-- (declared as an additionalField) — the user table does not exist yet when
-- these migrations run.
CREATE TABLE classrooms (
id TEXT PRIMARY KEY,
code TEXT NOT NULL,
created_by TEXT NOT NULL,
created_at TEXT NOT NULL,
expires_at TEXT NOT NULL,
ended_at TEXT,
cleaned_at TEXT
);

-- Codes are unique only among live classrooms; "live" depends on now(), so
-- uniqueness is enforced at creation time rather than by a constraint.
CREATE INDEX idx_classrooms_code ON classrooms(code);
Loading
Loading