Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
64dca85
Preserve room sessions across deploys
coder13 Jul 10, 2026
516cc09
Add API and socket health checks
coder13 Jul 10, 2026
366254c
Preserve active solves across deploys
coder13 Jul 11, 2026
bc91fa2
Merge pull request #178 from coder13/agent/deploy-safe-reconnect
coder13 Jul 11, 2026
9a1be2e
Fix private room reconnect recovery
coder13 Jul 12, 2026
49a1f3c
Merge pull request #179 from coder13/agent/private-room-rejoin
coder13 Jul 12, 2026
4745a30
Add shared scramble provider
coder13 Jul 12, 2026
d179f34
Fix Vite event catalog export
coder13 Jul 13, 2026
12a9169
Merge pull request #180 from coder13/agent/scramble-provider
coder13 Jul 13, 2026
0b9d9f0
Fix Docker shared workspace build
coder13 Jul 13, 2026
184af06
Merge pull request #182 from coder13/agent/docker-scrambles-workspace
coder13 Jul 13, 2026
87fce8f
Harden Docker Yarn installs
coder13 Jul 13, 2026
9f878e5
Merge pull request #183 from coder13/agent/docker-yarn-network
coder13 Jul 13, 2026
233220d
Refresh project documentation
coder13 Jul 13, 2026
c70e39b
Render 2D scramble previews for all events
coder13 Jul 13, 2026
0d89284
Merge pull request #184 from coder13/agent/scramble-previews
coder13 Jul 13, 2026
777f711
Remove WCA email from user data
coder13 Jul 13, 2026
72e1494
Make email purge fail closed
coder13 Jul 13, 2026
30afeeb
Build friendship lifecycle foundation
coder13 Jul 13, 2026
bc2f365
Stabilize room host ownership
coder13 Jul 13, 2026
1b92379
Normalize usernames for indexed lookup
coder13 Jul 13, 2026
35e3198
Harden normalized username rollout
coder13 Jul 13, 2026
eb0eadf
Harden friendship lifecycle ordering
coder13 Jul 13, 2026
b876759
Harden room departure handoffs
coder13 Jul 13, 2026
7f60660
Harden friendship quota recovery
coder13 Jul 13, 2026
9e572b4
Make room departures cross-process safe
coder13 Jul 13, 2026
7f99987
Make stale departure claims terminal
coder13 Jul 13, 2026
98d082b
Replace friendship quota with Redis limiter
coder13 Jul 13, 2026
af3602b
Fence duplicate room joins from stale leaves
coder13 Jul 13, 2026
e7d6859
Reauthorize recovered room joins
coder13 Jul 13, 2026
10400a8
Add typed social notification inbox
coder13 Jul 13, 2026
a338365
Create both users in notification Cypress flow
coder13 Jul 13, 2026
ca5ac71
Assert notification identity instead of display casing
coder13 Jul 13, 2026
c3df454
Merge PR #192: remove WCA email data
coder13 Jul 13, 2026
2120740
Merge PR #194: normalize usernames
coder13 Jul 13, 2026
7c102a2
Merge PR #193: friendship lifecycle
coder13 Jul 13, 2026
a73924a
Merge PR #195: preserve room ownership on rejoin
coder13 Jul 13, 2026
7ee0155
Merge PR #198: typed notification inbox
coder13 Jul 13, 2026
c436f21
Add privacy-safe user discovery
coder13 Jul 13, 2026
5cd4e02
Harden discovery privacy boundaries
coder13 Jul 13, 2026
6add0db
Limit public profile keys to discoverable users
coder13 Jul 13, 2026
ed0bdcc
Support distinct no-email Cypress identities
coder13 Jul 13, 2026
8cfefcb
Allow Cypress API origin overrides
coder13 Jul 13, 2026
4220b9d
Refine notification surfaces
coder13 Jul 13, 2026
f6eb716
Fix public profile navigation
coder13 Jul 14, 2026
3ebcb31
Separate profile and user discovery
coder13 Jul 14, 2026
3a38277
Add friends management flow
coder13 Jul 14, 2026
05e83e9
Improve responsive account navigation
coder13 Jul 14, 2026
8dc3add
Prioritize sent friend requests
coder13 Jul 14, 2026
44fc40e
Gate friends and add race invitations
coder13 Jul 14, 2026
ac8225b
Disable friends in production
coder13 Jul 14, 2026
6c99935
Merge remote-tracking branch 'origin/master'
coder13 Jul 14, 2026
5702f65
Merge branch 'dev'
coder13 Jul 14, 2026
2bf257f
Merge pull request #192 from coder13/agent/issue-191-no-wca-email
coder13 Jul 14, 2026
353e79a
Merge remote-tracking branch 'origin/master'
coder13 Jul 14, 2026
4d08999
Define Room and RaceSession contract
coder13 Jul 14, 2026
75f306e
Document RaceSession backfill contract
coder13 Jul 14, 2026
4f8c89a
Harden public user discovery
coder13 Jul 14, 2026
4e923d5
Enable social features in Cypress socket server
coder13 Jul 14, 2026
9fe3e02
Merge pull request #210 from coder13/agent/fix-ci-social-socket
coder13 Jul 14, 2026
e09957d
Merge branch 'master' into agent/issue-200-race-session-contract
coder13 Jul 14, 2026
9615170
Merge branch 'master' into agent/issue-175-room-session-backfill
coder13 Jul 14, 2026
7b0f142
Merge branch 'master' into agent/harden-user-discovery
coder13 Jul 14, 2026
c02247d
Forward production metrics configuration
coder13 Jul 14, 2026
69e60e8
Merge pull request #206 from coder13/agent/issue-200-race-session-con…
coder13 Jul 14, 2026
cb10736
Merge pull request #208 from coder13/agent/issue-175-room-session-bac…
coder13 Jul 14, 2026
911dc95
Merge pull request #209 from coder13/agent/harden-user-discovery
coder13 Jul 14, 2026
823cfd6
Merge pull request #207 from coder13/issue-176-metrics-production-config
coder13 Jul 14, 2026
3ea70c1
Modernize legacy dependencies
coder13 Jul 10, 2026
93843b2
Fix desktop MUI style precedence
coder13 Jul 10, 2026
d33a423
Fix clipped dialog form labels
coder13 Jul 10, 2026
cc9add6
Align current features with modern tooling
coder13 Jul 14, 2026
6fd622a
Fix modernized CI startup
coder13 Jul 14, 2026
520951b
Merge pull request #172 from coder13/agent/fix-dependency-issues
coder13 Jul 14, 2026
0c8045d
Fix Mongoose session authentication
coder13 Jul 14, 2026
3bc92d7
Merge pull request #224 from coder13/fix/mongoose-session-deserializa…
coder13 Jul 14, 2026
818fe9e
Harden API request handling
coder13 Jul 14, 2026
a09e16e
Update Cypress requests for CSRF
coder13 Jul 14, 2026
7bbbacb
Merge pull request #228 from coder13/agent/codeql-high-security
coder13 Jul 14, 2026
f268adb
Harden security test fixtures
coder13 Jul 14, 2026
4cf2e8e
Merge pull request #229 from coder13/agent/codeql-fixture-security
coder13 Jul 14, 2026
e18d2cd
Stabilize notification Cypress sessions
coder13 Jul 14, 2026
b971d45
Merge pull request #230 from coder13/agent/notification-cypress-stabi…
coder13 Jul 14, 2026
b05c72b
Isolate Cypress test-user sessions
coder13 Jul 14, 2026
b89c3da
Merge pull request #231 from coder13/agent/notification-cypress-sessi…
coder13 Jul 14, 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
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
NODE_ENV=prod
PORT=8080
SOCKETIO_PORT=9000
# Preserve room membership while clients reconnect after a socket deploy.
ROOM_RECONNECT_GRACE_MS=60000
# Grand Prix is intentionally disabled until the mode is redesigned.
GRAND_PRIX_ENABLED=false
# Friend System routes remain disabled through the #188 launch gate.
SOCIAL_FEATURES_ENABLED=false
# Manual Compose commands use this tag. scripts/deploy.sh overrides it with
# the full deployed commit SHA.
APP_IMAGE_TAG=local

# Public URLs used by the client build
Expand Down
17 changes: 17 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 10

- package-ecosystem: docker
directory: /
schedule:
interval: weekly

- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
14 changes: 12 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ on:
- master

jobs:
configuration:
name: Production configuration checks
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Validate production metrics configuration
run: scripts/test-compose-metrics-config.sh

server:
name: Server lint and unit tests
runs-on: ubuntu-latest
Expand Down Expand Up @@ -111,10 +121,10 @@ jobs:
run: docker compose -f compose.yml -f compose.dev.yml up -d mongo redis

- name: Start server
run: LETSCUBE_TEST_AUTH=true yarn workspace letscube-server node index.js > server.log 2>&1 &
run: LETSCUBE_TEST_AUTH=true SOCIAL_FEATURES_ENABLED=true POSTGRES_ENABLED=false yarn workspace letscube-server node index.js > server.log 2>&1 &

- name: Start socket server
run: yarn workspace letscube-server node socket/ > socket.log 2>&1 &
run: SOCIAL_FEATURES_ENABLED=true POSTGRES_ENABLED=false yarn workspace letscube-server node socket/ > socket.log 2>&1 &

- name: Wait for local stack
run: |
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: CodeQL

on:
pull_request:
push:
branches:
- master
schedule:
- cron: '23 10 * * 1'

permissions:
contents: read

jobs:
analyze:
name: Analyze JavaScript
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: javascript-typescript

- name: Analyze
uses: github/codeql-action/analyze@v4
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ client/config/.env.development
# Local build/worktree scratch
.turbo
.worktrees
.privacy-email-cutover
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
yarn lint && yarn test
124 changes: 66 additions & 58 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,81 @@
# Let's Cube Agent Gotchas
# Let's Cube Agent Guidelines

This file is intentionally short. It captures repo-specific traps that are easy
to miss when making changes here.
This file is only for durable, repository-specific instructions that change how
coding agents should work. Feature behavior, architecture, deployment details,
known bugs, and operational procedures belong in normal documentation and tests.
Do not duplicate them here.

## Project Layout
## Find The Source Of Truth

- This is a Yarn classic workspace monorepo. `client/` and `server/` are
workspaces, and the root `yarn.lock` is the only dependency lockfile.
- Root scripts are workspace-aware and mostly run through Turbo. Prefer root
commands like `yarn lint`, `yarn test`, and `yarn build` unless you need a
narrow workspace command.
- Read the relevant README, `docs/` file, tests, configuration, and surrounding
code before changing behavior. Prefer those sources over conversation history
or assumptions from similarly named branches.
- When a change introduces a durable feature rule or operational procedure,
update the owning documentation or tests instead of adding it to this file.
- Keep this file short. Do not use it for task status, backlog notes, temporary
workarounds, or descriptions of individual features.

## Runtime Setup
## Keep Changes Focused

- Local development needs MongoDB and Redis.
- The repo targets Node 22. Install from the repo root with `yarn install`.
- The backend is two separate processes:
- `yarn start:server` starts Express/static/auth/API on port `8080`.
- `yarn start:socket` starts Socket.IO on port `9000`.
- The client runs separately with `yarn start:client`.
- Client env values live in `client/.env.development` and expect the API at
`http://localhost:8080` and Socket.IO at `http://localhost:9000`.
- Match existing project patterns and make the smallest coherent change. The
repository contains legacy and modernized areas side by side, so avoid broad
rewrites or dependency upgrades unless they are part of the task.
- Do not mix cleanup, refactoring, generated-file churn, or unrelated fixes into
a feature branch. Preserve pre-existing user changes and untracked files.
- If the requested direction changes, remove the abandoned implementation before
building the replacement.

## Dependency Age
## Code Structure And Comments

- The stack is old: React 16, Webpack 4, Material UI v4, Socket.IO v3,
Mongoose 6, and a customized CRA/Webpack toolchain.
- Be cautious with modern Node/npm changes. The old CRA/Webpack toolchain is
likely to be the first thing to break.
- Prefer clear names and structure over comments. Add a comment only to explain a
non-obvious invariant, external constraint, compatibility requirement, safety
concern, or intentional tradeoff. Explain why, not what the next line does.
- Do not leave development narration, conversation history, commented-out code,
or vague TODO/FIXME notes. Link actionable follow-up work to an issue, and
update or remove comments when the surrounding behavior changes.
- Keep functions cohesive and easy to understand, but do not mechanically
extract every expression. A function should own a meaningful unit of behavior,
not merely wrap a one-liner unless an interface or callback requires it.
- Treat a convoluted function name as a design smell: simplify the responsibility
or keep the operation inline. Split functions that mix responsibilities or
accumulate difficult branching, without maximizing the number of functions.
- Do not add speculative abstractions, configuration, or fallback paths for
hypothetical future needs. Implement the current contract and make violated
invariants visible instead of silently masking them.

## Socket.IO
## Branch And Worktree Hygiene

- Socket protocol constants live in `client/src/lib/protocol.js` and are also
imported by the server. Update protocol constants, client middleware, and
server namespace handlers together.
- `Protocol.ERROR` intentionally maps to the literal event name `errorrr`.
Do not casually rename it to `error`, which can collide with Socket.IO's own
error behavior.
- Client socket connections are owned by Redux middleware in
`client/src/store/middlewares/`, not by React components.
- Echo-style socket features often need separate incoming and outgoing events.
Reusing one event for both directions can create infinite loops.
- This repository often has several active worktrees and stale local branches.
Confirm the current worktree, branch, status, and merge base before editing.
- Start unrelated work in a fresh branch and worktree so active changes remain
isolated. Unless explicitly told otherwise, fetch first and create the new
worktree from `origin/master`, not from the currently checked-out feature
branch.
- Before publishing, inspect both the commit list and
`git diff --stat origin/master...HEAD`. Rebase or cherry-pick onto the intended
base if the diff contains unrelated work.

## Room State
## Monorepo Discipline

- Room user state uses Mongoose `Map`s keyed by WCA numeric user ids converted
to strings. Preserve that convention when reading or writing maps like
`waitingFor`, `competing`, `banned`, `inRoom`, and `registered`.
- Room data is deliberately masked differently for lobby users and joined users
in `server/socket/namespaces/rooms.js`.
- Normal rooms are marked stale with `expireAt` TTL when empty. Grand Prix rooms
are timer-driven and have different lifecycle behavior.
- This is a Yarn classic workspace monorepo. Install from the repository root,
use the root `yarn.lock`, and do not create workspace-level lockfiles.
- Prefer root Turbo commands for broad checks and workspace-filtered commands
for focused iteration. Follow existing package boundaries rather than adding
cross-workspace source imports.
- Before adding a dependency, check whether the platform or an existing
dependency already solves the problem clearly. Add it only to the workspace
that uses it and explain non-obvious choices.

## Auth And Sessions
## Local Machine Gotcha

- Express sessions are stored in MongoDB and shared with Socket.IO through
`express-socket.io-session`.
- Client API requests use `credentials: 'include'`; auth, CORS, and socket
changes need to preserve cookie behavior.
- WCA OAuth uses the `redirectUri` sent by the client. The mixed
`callbackUrl`/`callbackURL` config spelling is not currently the source of
truth for the auth redirect.
- Use the system Docker engine on this machine. The Docker Desktop context is
unreliable, so inspect the current context and run project Compose commands
with `DOCKER_CONTEXT=default`.

## Checks
## Verification And Handoff

- Tests are sparse. The server test script currently passes when no tests exist.
- The root pre-commit hook runs `yarn lint && yarn test`.
- Useful focused checks:
- `yarn turbo run lint --filter=letscube-client`
- `yarn turbo run test:ci --filter=letscube-client`
- `yarn turbo run lint --filter=letscube-server`
- `yarn turbo run test:ci --filter=letscube-server`
- Run the narrowest meaningful lint and tests while iterating, then broaden
checks when a change crosses workspace or runtime boundaries.
- Before handoff, review the complete diff for scope, run `git diff --check`,
and state exactly which checks passed, failed, or were not run.
- When committing, include a concise body explaining what changed and why.
128 changes: 85 additions & 43 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,69 +1,111 @@
The project is split into 2 parts: the server, and the client.
# Contributing to Let's Cube

# Sending a Pull Request
Thank you for helping improve Let's Cube. Keep changes focused, preserve the
existing behavior outside the task, and include tests when behavior changes.

1. Fork the repo
2. Clone it to your machine
## Before You Start

```bash
git clone git@github.com:<yourusername>/letscube.git
cd letscube
git remote add upstream git@github.com:coder13/letscube.git
```
Read the [development guide](docs/development.md) and the documentation for the
area being changed. The repository targets Node `22.17.0`, Yarn classic, and
Docker Compose.

3. Sync your local `master` branch with upstream:
```bash
get checkout master
git pull upstream master
```
Install dependencies once from the repository root:

4. Create a new feature branch:
```bash
git checkout -b feature-branch
```sh
nvm use
corepack enable
yarn install --frozen-lockfile
```

5. Commit and push the changes:
```bash
git push -u
Do not run separate installs or create lockfiles inside workspaces.

## Branches

Create branches from the latest `master`:

```sh
git fetch origin
git switch -c your-branch origin/master
```

7. Go to the [repository](https://github.com/coder13/letscube) and make a Pull Request to the `dev` branch.
If you use a fork, replace `origin` with the remote that tracks the canonical
repository. Pull requests should target `master`.

Keep each pull request limited to one coherent change. Before publishing,
inspect both the commit list and the complete diff against `master` to make sure
the branch does not include work inherited from another feature branch.

## Code Style

# Installing and Running:
- Follow the surrounding JavaScript and React patterns.
- The client and server use ESLint configurations based on Airbnb's style.
- Prefer small modules organized by responsibility over broad rewrites.
- Add comments only when they explain a non-obvious constraint or decision.
- Avoid unrelated formatting, dependency, or generated-file churn.

`npm install` in the root directory installs the pre-commit hook.
The repository contains modernized and legacy areas side by side. A change does
not need to modernize adjacent code unless that work is part of its purpose.

## to start the bash server:
## Tests And Checks

```bash
cd server/
npm install
npm start
Run focused checks while iterating:

```sh
yarn turbo run lint --filter=letscube-client
yarn turbo run test:ci --filter=letscube-client

yarn turbo run lint --filter=letscube-server
yarn turbo run test:ci --filter=letscube-server

yarn turbo run lint --filter=letscube-scrambles
yarn turbo run test:ci --filter=letscube-scrambles
```

## to start the client dev server:
Run the broad checks before requesting review when the change crosses workspace
boundaries:

```bash
cd client/
npm install
npm start
```sh
yarn lint
yarn test
yarn build
```
# Pre-commit hook

When installed properly, the pre-commit hook won't let you commit without the client and server being properly linted and tests being ran.
Use `yarn cypress:run` for behavior that spans the browser, API, and Socket.IO
server. See [Development](docs/development.md#full-stack-cypress) for the local
stack expected by Cypress.

# Linting
Every behavior change should have a test at the narrowest useful layer. UI
changes should include screenshots or a short recording in the pull request.

Both the client and the server use eslint and a slight variation of [airbnb's style guide](https://github.com/airbnb/javascript).
## Database Changes

PostgreSQL schema changes must be represented in Prisma and committed as a
migration. Validate them with:

```sh
yarn workspace letscube-server postgres:schema:validate
yarn workspace letscube-server postgres:migrate
yarn workspace letscube-server postgres:schema:check
```

# Tests
Migrations must remain compatible with the previously deployed application
image because application rollback does not reverse database migrations. Read
[Data and migrations](docs/data.md) before changing persistence.

LetsCube is currently using Jest and Enzyme for testing. Right now there is very minimal tests but I would like to add much more coverage in time. For any complicated computational code, it should be tested to make sure there are no errors.
## Pull Requests

# Nit picky stuff:
A pull request should include:

This project uses React: A component should be made whenever something gets too complicated (like with the timesTable) or if it's going to be used repeatedly.
- the problem and intended behavior;
- a concise summary of the implementation;
- the checks that passed, failed, or were not run;
- migration, deployment, or compatibility considerations;
- screenshots for visible UI changes; and
- links to relevant issues.

Redux: I'd like to keep the number of reducers relatively low. Please get in contact with me before adding another reducer.
Write commit subjects in the imperative mood. Include a short commit body that
explains what changed and why.

Socket.IO: A common code pattern I found myself using is socket events to send information from a client and a separate event to echo the data to clients. If not done properly and one event was used for both, an infinite loop would happen. Take this into consideration when creating events that echo to other users.
Do not include credentials, production data, access tokens, or private logs. If
you discover a vulnerability, follow [SECURITY.md](SECURITY.md) instead of
opening a public issue.
Loading
Loading