From 9e5b33d8f0ac8364600f188f487e118b9b66a100 Mon Sep 17 00:00:00 2001 From: Naman Rusia Date: Thu, 24 Sep 2026 01:44:32 -0400 Subject: [PATCH 1/3] Add docs and a Makefile, and bring local Postgres to 17 docs/ holds development, architecture, judge and sandbox, and self-hosting pages, plus decision records. Pages name the file or constant that holds a value instead of copying it, decision records are append-only, and a CI job fails on any relative Markdown link that no longer resolves. Also for contributors: a Makefile for the everyday commands, issue forms, SECURITY.md, Dependabot (monthly, grouped, monaco-editor held), an editorconfig, a Node version file, a documented web .env.example, and a docs prompt in the pull request template. Local Postgres was 13 while CI and production run 17. It is now 17 on a volume named for the version, so an existing 13 volume is left alone instead of failing to start. --- .editorconfig | 18 +++ .github/ISSUE_TEMPLATE/bug.yml | 34 +++++ .github/ISSUE_TEMPLATE/config.yml | 5 + .github/ISSUE_TEMPLATE/problem.yml | 31 ++++ .github/PULL_REQUEST_TEMPLATE.md | 4 + .github/dependabot.yml | 27 ++++ .github/workflows/docs.yml | 21 +++ AGENTS.md | 13 +- CONTRIBUTING.md | 8 +- Makefile | 40 +++++ README.md | 144 ++++-------------- SECURITY.md | 23 +++ apps/backend/docker-compose.yml | 8 +- apps/web/.env.example | 10 ++ apps/web/.env.template | 1 - apps/web/.nvmrc | 1 + docs/README.md | 21 +++ docs/architecture.md | 58 +++++++ .../0001-one-host-for-the-backend.md | 18 +++ docs/decisions/0002-a-container-per-run.md | 18 +++ .../0003-the-server-relays-the-editor.md | 18 +++ .../decisions/0004-problems-are-migrations.md | 18 +++ docs/decisions/README.md | 30 ++++ docs/development.md | 80 ++++++++++ docs/judge-and-sandbox.md | 33 ++++ docs/self-hosting.md | 56 +++++++ 26 files changed, 613 insertions(+), 125 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/ISSUE_TEMPLATE/bug.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/problem.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/docs.yml create mode 100644 Makefile create mode 100644 SECURITY.md create mode 100644 apps/web/.env.example delete mode 100644 apps/web/.env.template create mode 100644 apps/web/.nvmrc create mode 100644 docs/README.md create mode 100644 docs/architecture.md create mode 100644 docs/decisions/0001-one-host-for-the-backend.md create mode 100644 docs/decisions/0002-a-container-per-run.md create mode 100644 docs/decisions/0003-the-server-relays-the-editor.md create mode 100644 docs/decisions/0004-problems-are-migrations.md create mode 100644 docs/decisions/README.md create mode 100644 docs/development.md create mode 100644 docs/judge-and-sandbox.md create mode 100644 docs/self-hosting.md diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..2d33154 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[*.py] +indent_size = 4 + +[Makefile] +indent_style = tab + +[*.md] +trim_trailing_whitespace = false diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 0000000..8d34a01 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,34 @@ +name: Bug report +description: Something in TandemCode does not work as it should. +labels: [bug] +body: + - type: textarea + id: what + attributes: + label: What happened + description: What you did, what you expected, and what you saw instead. + validations: + required: true + - type: textarea + id: steps + attributes: + label: Steps to reproduce + placeholder: | + 1. Open a room + 2. ... + validations: + required: true + - type: dropdown + id: where + attributes: + label: Where + options: + - tandemcode.space + - A local checkout + validations: + required: true + - type: textarea + id: details + attributes: + label: Browser, logs, screenshots + description: Browser and OS, any errors from the browser console, and API or runner logs if you run it locally. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..9d16cb5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: true +contact_links: + - name: Report a security vulnerability + url: https://github.com/naman0r/tandemcode/security/advisories/new + about: Please report vulnerabilities privately, not in a public issue. See SECURITY.md. diff --git a/.github/ISSUE_TEMPLATE/problem.yml b/.github/ISSUE_TEMPLATE/problem.yml new file mode 100644 index 0000000..8b10e1b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/problem.yml @@ -0,0 +1,31 @@ +name: Problem proposal +description: Suggest a practice problem. If you can write it yourself, CONTRIBUTING.md shows how. +labels: [problem] +body: + - type: input + id: title + attributes: + label: Problem + placeholder: Move Zeroes + validations: + required: true + - type: textarea + id: statement + attributes: + label: Statement + description: The task in your own words, with one example input and output. Do not paste text from other sites. + validations: + required: true + - type: dropdown + id: difficulty + attributes: + label: Difficulty + options: [easy, medium, hard] + validations: + required: true + - type: checkboxes + id: pr + attributes: + label: Contribution + options: + - label: I would like to open the pull request for this myself. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 605dc33..d76edbd 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -5,3 +5,7 @@ ## How this was verified + +## Docs + + diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..4c71fa5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,27 @@ +# Monthly and grouped, so updates arrive as one pull request per ecosystem. +version: 2 +updates: + - package-ecosystem: npm + directory: /apps/web + schedule: + interval: monthly + groups: + web: + patterns: ["*"] + ignore: + # Pinned on purpose. Upgrade it by hand and check the shared editor. + - dependency-name: monaco-editor + - package-ecosystem: pip + directory: /apps/backend + schedule: + interval: monthly + groups: + backend: + patterns: ["*"] + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly + groups: + actions: + patterns: ["*"] diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..c74abe4 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,21 @@ +name: Docs + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +jobs: + links: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + # Relative links only: a moved or deleted file fails the build, and an + # outside site being down does not. + - uses: lycheeverse/lychee-action@v2 + with: + args: --offline --no-progress --exclude-path node_modules './**/*.md' diff --git a/AGENTS.md b/AGENTS.md index 8948527..e7ce195 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,8 +2,17 @@ ## Local checks -- Backend: `cd apps/backend && docker compose up -d db && docker compose run --rm -v "$PWD:/workspace" backend sh -lc 'cd /workspace && HOME=/tmp pip install -r requirements-dev.txt && HOME=/tmp python -m pytest'` -- Web: `cd apps/web && npm run lint && npm run build` +- Everything CI runs: `make check`. `make` lists the other commands. +- Backend only: `make test` (runs pytest in the API image against the compose database). +- Web only: `make lint` (lint and production build). + +## Docs + +- Start at `docs/README.md`. `docs/architecture.md` says where each part of the system lives. +- A change to how something works updates the page that describes it, in the same pull request. +- Docs name the constant or file that holds a value; they do not copy the value. +- `docs/decisions/` records are never edited. A changed decision gets a new record. +- `docs/internal/` is gitignored and never committed. ## Content rules diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6cfc504..f825145 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,9 @@ # Contributing -Pull requests are welcome. `README.md` explains how to run the app locally and -which checks CI runs; run those before opening a pull request. +Pull requests are welcome. [docs/development.md](docs/development.md) explains +how to run the app locally and make common changes. Run `make check`, which is +what CI runs, before opening a pull request. For anything larger than a small +fix, open an issue first so we can agree on the approach. ## Adding a problem @@ -125,7 +127,7 @@ in your migration, hidden ones included. It fails if: ### 5. Check it -Run the backend checks from `README.md`. To see the problem in the app, +Run `make test`. To see the problem in the app, restart the API so the migration runs: ```bash diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c4921fb --- /dev/null +++ b/Makefile @@ -0,0 +1,40 @@ +# Everyday commands. `make` alone lists them. +BACKEND := apps/backend +WEB := apps/web +COMPOSE := docker compose -f $(BACKEND)/docker-compose.yml + +.DEFAULT_GOAL := help +.PHONY: help setup up down logs web test lint check smoke + +help: ## List the commands + @grep -E '^[a-z]+:.*## ' $(MAKEFILE_LIST) | awk -F ':.*## ' '{ printf " make %-7s %s\n", $$1, $$2 }' + +setup: ## Copy the env templates and install web dependencies + @test -f $(BACKEND)/.env || cp $(BACKEND)/.env.example $(BACKEND)/.env + @test -f $(WEB)/.env || cp $(WEB)/.env.example $(WEB)/.env + cd $(WEB) && npm install + @echo "Now fill in DB_PASSWORD and the Clerk keys in $(BACKEND)/.env and $(WEB)/.env" + +up: ## Start Postgres, the API and the runner + $(COMPOSE) up -d --build + +down: ## Stop them + $(COMPOSE) down + +logs: ## Follow the API and runner logs + $(COMPOSE) logs -f backend runner + +web: ## Run the web app at http://localhost:5173 + cd $(WEB) && npm run dev + +test: ## Backend tests, in the API image against the compose database + $(COMPOSE) up -d db + $(COMPOSE) run --rm -v "$(CURDIR)/$(BACKEND):/workspace" backend sh -lc 'cd /workspace && HOME=/tmp pip install -q -r requirements-dev.txt && HOME=/tmp python -m pytest' + +lint: ## Web lint and production build + cd $(WEB) && npm run lint && npm run build + +check: test lint ## Everything CI runs + +smoke: ## Check a deployment: make smoke [SITE=...] [API=...] + ./infra/smoke.sh $(or $(SITE),https://tandemcode.space) $(or $(API),https://api.tandemcode.space) diff --git a/README.md b/README.md index 7279e01..41fd267 100644 --- a/README.md +++ b/README.md @@ -1,136 +1,46 @@ # TandemCode -Real-time pair programming with a judge. Two people share a room, edit the same -code in a Monaco editor, chat, pick a problem, and run their solution against -hidden tests. +Practice coding problems with a partner. Two people share a room, edit the same code, chat, and run their solution against the problem's tests together. Afterwards the whole session can be replayed. -## What works today +It runs at [tandemcode.space](https://tandemcode.space). It is free and open source under the Apache License 2.0. -- Clerk sign-in. Every API route and both websockets verify a session token. -- Rooms: create, join by id, presence, chat, owner assigns a problem. -- Shared editor: Yjs over a websocket relay, one document per room. -- Problems: statement, starter code, public samples, hidden tests, for all - fifteen seeded problems. -- Run: a runner process judges Python submissions against the tests with time - and memory limits and the room shows the verdict and the first failing test. +## What it does -## What does not exist yet - -- A queue or separate judge hosts. The runner takes work from the submissions - table on the API host. See #33. -- Complexity estimates, counterexamples, languages other than Python. - -## Stack - -| Piece | Choice | -| --- | --- | -| Web | React 19, Vite, TypeScript, Tailwind, Monaco, Yjs, Clerk | -| API | FastAPI on Python 3.11, asyncpg, raw JSON over websockets | -| Runner | Same image as the API, `python -m app.runner` | -| Database | Postgres 17 in production and CI (13 in the local compose), forward-only SQL migrations in `apps/backend/migrations` | -| CI | pytest with a Postgres service; web lint and build | - -## Layout - -``` -apps/ - backend/ - app/ - core/ settings, Clerk token verification - routes/ HTTP endpoints - services/ rules, take an authenticated caller id - dao/ all SQL - websocket/ room chat and Yjs relay - runner/ judge and the polling worker - migrations/ V__.sql - tests/ - web/ - src/ - routes/ pages: /, /dashboard, /rooms, /rooms/create, /rooms/join, /rooms/:id, /problems - components/ editor, chat, members, header - hooks/ room websocket - lib/ API client, auth, config -infra/ production compose, Caddy, host scripts -``` - -Requests flow routes to services to dao. Authentication happens at the HTTP -and websocket boundary; services never see a token. +- Rooms that are public or unlisted, shared by invite link, with a way to ask for a partner. +- One shared editor with live cursors, built on Yjs. +- Problems with starter code, visible examples and hidden tests, added by pull request. +- Python submissions judged in an isolated container per run, with the verdict shown to everyone in the room. +- A replay of each session: the code as it was typed, the chat and every run. ## Run it locally -You need Docker, Node 20.19 or later, and a Clerk application. +You need Docker, Node 22 and a free Clerk application. ```bash -cd apps/backend -cp .env.example .env # set DB_PASSWORD, CLERK_ISSUER, CLERK_SECRET_KEY -docker compose up -d --build # db on 5433, api on 8080, runner - -cd ../web -cp .env.template .env # set VITE_CLERK_PUBLISHABLE_KEY -npm install -npm run dev # http://localhost:5173 +make setup # copy the .env templates, install web dependencies + # then fill in the Clerk keys and a DB password +make up # Postgres, the API and the runner +make web # http://localhost:5173 ``` -Migrations run when the API starts. The runner waits for the API's health -check, so it never sees a half-migrated schema. +[docs/development.md](docs/development.md) has the details, the checks and the common changes. -To serve the built web app from nginx instead of Vite, add -`VITE_CLERK_PUBLISHABLE_KEY` to apps/backend/.env and run -`docker compose --profile prod up -d --build`. The app is on port 3000. - -To run the API outside Docker instead: - -```bash -cd apps/backend -python3.11 -m venv .venv && .venv/bin/pip install -r requirements.txt -.venv/bin/uvicorn app.main:app --port 8080 --reload -.venv/bin/python -m app.runner -``` - -## Checks - -```bash -cd apps/backend && docker compose run --rm -v "$PWD:/workspace" backend \ - sh -lc 'cd /workspace && HOME=/tmp pip install -r requirements-dev.txt && HOME=/tmp python -m pytest' -cd apps/web && npm run lint && npm run build -``` - -Tests use a `tandemcode_test` database that is dropped and recreated per run. - -## Judge contract - -A problem's tests are `[{"input", "expected", "hidden"}]`. The program reads -stdin and prints; a test passes when trimmed stdout equals the trimmed -expected string. The runner stops at the first failure. Statuses are -`accepted`, `wrong_answer`, `runtime_error` and `time_limit_exceeded`. The -judge is a pure function in `apps/backend/app/runner/judge.py`, so a hosted -runner can call the same thing. - -## Sandbox - -With `SANDBOX_IMAGE` set, as it is in docker compose, the runner judges each -submission in a fresh container from that image: no network, read-only root, -a 64 MB `/tmp`, uid 65534, all capabilities dropped, a memory cap and 32 -processes. Without it the runner refuses to start, unless `ALLOW_UNSANDBOXED=1` -is set, in which case it judges in-process with rlimits only: fine for tests, -not for strangers' code. Output of hidden tests is never returned. - -Containers share the host kernel, so one kernel bug is enough to escape them. -With `SANDBOX_RUNTIME=runsc` each judge container runs under gVisor, which -handles the program's system calls in its own user-space kernel; production -sets it, and `infra/install-gvisor.sh` installs it on an Ubuntu host. +## Stack -The runner reaches Docker through the host's socket, so the runner itself is -as trusted as the host. Keep it on a machine that runs nothing else. +- Web: React 19, Vite, TypeScript, Tailwind, Monaco, Yjs, Clerk. +- API: FastAPI on Python 3.11 with asyncpg, HTTP plus two websockets. +- Runner: the API's image running `python -m app.runner`, judging in Docker containers under gVisor. +- Database: Postgres 17 with forward-only SQL migrations. +- Production: one Linux host with Docker Compose and Caddy, and the web app on Vercel. -## Deploy +## Docs -`infra/` runs the API, runner, Postgres and Caddy on one Docker host with -`docker compose -f infra/docker-compose.prod.yml up -d --build`; settings go in -`infra/.env` (see `infra/.env.example`). The web app is a static Vite build, -with `apps/web/vercel.json` for Vercel. +- [Development](docs/development.md) +- [Architecture](docs/architecture.md) +- [Judge and sandbox](docs/judge-and-sandbox.md) +- [Self-hosting](docs/self-hosting.md) +- [Decisions](docs/decisions/) ## Contributing -`CONTRIBUTING.md` covers pull requests and how to add a problem. `AGENTS.md` -has the rules for agents and the same checks as above. +Pull requests are welcome, and adding a problem is the easiest place to start. [CONTRIBUTING.md](CONTRIBUTING.md) explains both. Report security issues privately as described in [SECURITY.md](SECURITY.md). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..9386d7f --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,23 @@ +# Security + +## Reporting a vulnerability + +Report it privately through GitHub: open the repository's Security tab and choose "Report a vulnerability". Please do not open a public issue or pull request for it. Include what you found, how to reproduce it, and what it lets someone do. + +Only tandemcode.space and the latest `main` are supported. Fixes land on `main` and are deployed from there. + +## In scope + +- Getting out of the judge's sandbox, or running code on the host. +- Signing in as someone else, or acting as another user. +- Reading or changing a room, its runs or its chat without having been in it. +- Taking the site down, or running up its hosting bill, from one account. + +The protections are described in [docs/judge-and-sandbox.md](docs/judge-and-sandbox.md) and [docs/architecture.md](docs/architecture.md). + +## Not a vulnerability + +- Reading a problem's hidden tests. They are public in the migrations that add them. +- Findings that need access to the host, the database or a maintainer's account. + +Please test against your own local copy rather than tandemcode.space, and never against other people's rooms or accounts. diff --git a/apps/backend/docker-compose.yml b/apps/backend/docker-compose.yml index 1a0517d..711c49a 100644 --- a/apps/backend/docker-compose.yml +++ b/apps/backend/docker-compose.yml @@ -2,7 +2,8 @@ # ${VAR:?...} makes Compose fail loudly instead of substituting an empty string. services: db: - image: postgres:13 + # The same major version as production and CI. + image: postgres:17 container_name: tandemcode-db environment: POSTGRES_DB: ${DB_NAME:?missing DB_NAME - copy .env.example to .env} @@ -100,4 +101,7 @@ services: volumes: db-data: - name: tandemcode-db-data + # Postgres cannot open another major version's data files, so the volume + # is named for the version. An old tandemcode-db-data volume is unused and + # can be removed with `docker volume rm tandemcode-db-data`. + name: tandemcode-db-data-17 diff --git a/apps/web/.env.example b/apps/web/.env.example new file mode 100644 index 0000000..c623c47 --- /dev/null +++ b/apps/web/.env.example @@ -0,0 +1,10 @@ +# Template. Copy to .env and fill in the key: +# cp .env.example .env +# .env is gitignored. Both values end up in the browser bundle, so neither is +# a secret. + +# Clerk dashboard -> API keys -> Publishable key. +VITE_CLERK_PUBLISHABLE_KEY= + +# Where the browser reaches the API. Websocket URLs are derived from it. +VITE_BACKEND_URL=http://localhost:8080 diff --git a/apps/web/.env.template b/apps/web/.env.template deleted file mode 100644 index 5142367..0000000 --- a/apps/web/.env.template +++ /dev/null @@ -1 +0,0 @@ -VITE_CLERK_PUBLISHABLE_KEY=YOUR_PUBLISHABLE_KEY \ No newline at end of file diff --git a/apps/web/.nvmrc b/apps/web/.nvmrc new file mode 100644 index 0000000..2bd5a0a --- /dev/null +++ b/apps/web/.nvmrc @@ -0,0 +1 @@ +22 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..a4035bf --- /dev/null +++ b/docs/README.md @@ -0,0 +1,21 @@ +# Docs + +Start with the page for what you are doing. + +- [Development](development.md): run TandemCode locally, run the checks, and make common changes. +- [Architecture](architecture.md): the parts of the system, how a request and a run move through them, and where each piece lives in the code. +- [Judge and sandbox](judge-and-sandbox.md): how submissions are judged and what isolates them. +- [Self-hosting](self-hosting.md): run your own instance on one Linux host. +- [Decisions](decisions/): why the system is shaped the way it is. + +Adding a problem is in [CONTRIBUTING.md](../CONTRIBUTING.md). + +## Keeping these pages current + +These pages go stale when they copy what the code already says. So they follow a few rules: + +1. Explain what and why. Leave exact values in the code. A page names the constant or file that holds a limit, port or timeout (`MAX_SOCKETS_PER_USER` in `app/websocket/room_chat.py`), and does not repeat its value. +2. Link to files and directories, not line numbers. +3. Change a page in the same pull request as the behaviour it describes. The pull request template asks. +4. Decision records are written once and not edited. When a decision changes, add a new record that replaces the old one, and mark the old one as replaced. +5. CI checks every relative link in the repository's Markdown, so a moved or deleted file fails the build. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..ed0d276 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,58 @@ +# Architecture + +TandemCode has five parts: + +- The web app (`apps/web`), a React single-page app built with Vite. In production it is static files on Vercel. +- The API (`apps/backend/app`), a FastAPI process that serves HTTP under `/api` and two websockets under `/ws`. +- The runner (`apps/backend/app/runner`), a separate process from the same image that judges submissions. +- Postgres, which holds everything: users, rooms, chat, editor history, problems and submissions. +- Clerk, which signs people in. TandemCode stores no passwords. + +In production Caddy sits in front of the API and terminates TLS. See [self-hosting](self-hosting.md). + +## Signing in + +The browser signs in with Clerk and gets a short-lived session token. It sends that token as a bearer header on HTTP calls, and as a `token` query parameter when it opens a websocket, because browsers cannot set headers on websockets. + +The API verifies the token at the edge and nowhere else: `app/core/auth.py` checks the signature against Clerk's keys, the issuer and the origin that requested it. Routes and websocket handlers turn it into a user id, and everything past that point works with the id. A user's name and email come from Clerk's API (`app/core/clerk.py`), never from the browser. + +## A request + +HTTP requests go from `app/routes/` to `app/services/` to `app/dao/`. Routes parse input and authenticate. Services hold the rules: who may read a room, who may change its problem, how many rooms or runs a user may start per hour. DAOs hold all the SQL, written by hand for asyncpg. Rate limits that must hold under parallel requests are enforced inside a transaction in the DAO, not by counting first and inserting later. + +## A room + +A room has two websockets, and the web app opens one of each: + +- `/ws/room/{id}` (`app/websocket/room_chat.py`) carries presence, chat, submission updates and problem changes as JSON. Joining it is what puts you on the room's roster. The server stamps every chat message with the sender's identity and time; the client sends only text. +- `/ws/yjs/{id}` (`app/websocket/yjs.py`) carries the shared editor. The document is a [Yjs](https://yjs.dev) CRDT, and the server does not hold a copy. It relays each frame from one peer to the others and answers for an empty document when someone is alone. It checks each frame's framing and rate before relaying it, and it records document changes in `room_updates` for the replay. + +Sends to many sockets go through `app/websocket/fanout.py`, which sends to each in parallel with a deadline, so one peer that stops reading cannot hold up the room. Per-user socket caps, frame budgets and chat limits are constants at the top of `room_chat.py` and `yjs.py`. + +Rooms are public or unlisted, and the owner can ask for a partner, which highlights the room on the rooms page. Reading a room's runs, roster or replay requires having been in it. + +## A run + +1. `POST /api/submissions` stores the code as a pending submission and tells the room that a run started. +2. The runner (`app/runner/__main__.py`) claims the oldest pending submission, judges it (see [judge and sandbox](judge-and-sandbox.md)), and stores the verdict. +3. Storing a verdict sends a Postgres `NOTIFY`. The API listens for it (`app/websocket/verdicts.py`) and broadcasts the verdict to the room. + +The runner polls for work and handles one submission at a time. A submission left running by a runner that died is put back in the queue when a runner starts. + +## Replay + +When a room closes, its history stays. `GET /api/rooms/{id}/replay` returns the recorded editor changes, the chat and the runs, and the web app (`apps/web/src/routes/rooms/Replay.tsx`) plays them back. Each room has a recording budget (`MAX_RECORDED_BYTES_PER_ROOM` in `yjs.py`), after which it keeps relaying but stops recording. + +## Data + +The schema is the SQL in `apps/backend/migrations/`, applied in order by `app/migrate.py` when the API starts. Problems are rows too. Each one is added by a migration, which is why contributing a problem is a pull request. + +## Where to change what + +- A page or component: `apps/web/src/routes/`, `apps/web/src/components/`. +- The API client and websocket URLs: `apps/web/src/lib/api.ts`, `apps/web/src/lib/config.ts`. +- An endpoint's rules: `apps/backend/app/services/`. +- A query: `apps/backend/app/dao/`. +- Realtime behaviour: `apps/backend/app/websocket/`. +- Judging: `apps/backend/app/runner/`. +- Production: `infra/`. diff --git a/docs/decisions/0001-one-host-for-the-backend.md b/docs/decisions/0001-one-host-for-the-backend.md new file mode 100644 index 0000000..7e30064 --- /dev/null +++ b/docs/decisions/0001-one-host-for-the-backend.md @@ -0,0 +1,18 @@ +# 0001. One host for the backend + +Status: accepted, 2026-09-23 + +## Context + +The runner starts a container for every submission, so it needs a Docker daemon. The managed container platforms considered do not give a container access to one. The project also has no budget beyond a few dollars a month, and a launch on public forums can bring bursts of traffic. + +## Decision + +The API, the runner, Postgres and Caddy run with Docker Compose on one Linux host (`infra/docker-compose.prod.yml`). tandemcode.space uses a 2 GB AWS Lightsail instance, which has a fixed monthly price with transfer included. The web app is a static build on Vercel, which deploys every push to `main`. The API deploys by hand with `infra/deploy.sh`. + +## Consequences + +- The whole backend costs one flat monthly price, and nothing in it scales its bill with traffic. +- Moving hosts is a dump, a restore and a DNS change, because the host runs nothing but Compose. +- One host is one point of failure. Automatic disk snapshots and nightly dumps cover data loss, not downtime. +- The runner shares a machine with the API, so a heavy judging load slows the API. Separate judge hosts are the next step if that happens. diff --git a/docs/decisions/0002-a-container-per-run.md b/docs/decisions/0002-a-container-per-run.md new file mode 100644 index 0000000..abaf49f --- /dev/null +++ b/docs/decisions/0002-a-container-per-run.md @@ -0,0 +1,18 @@ +# 0002. A container per run + +Status: accepted, 2026-09-23 + +## Context + +Anyone can sign up and submit code, so every submission may be hostile. Resource limits inside the runner's own process stop runaway programs but not a program that reads files or opens connections. + +## Decision + +Each submission is judged in a new container with no network, a read-only filesystem, an unprivileged user and memory and process caps (`app/runner/sandbox.py`). In production the container runs under gVisor, so the program's system calls go to gVisor's kernel rather than the host's. + +## Consequences + +- Getting out of the sandbox takes a gVisor bug and then a kernel bug. +- Starting a container adds time to every run. +- The runner holds the host's Docker socket, so it is as trusted as the host. The host runs nothing else. +- The runner judges one submission at a time. More runners, or runners on other hosts, need a change to how work is claimed. diff --git a/docs/decisions/0003-the-server-relays-the-editor.md b/docs/decisions/0003-the-server-relays-the-editor.md new file mode 100644 index 0000000..2324f0f --- /dev/null +++ b/docs/decisions/0003-the-server-relays-the-editor.md @@ -0,0 +1,18 @@ +# 0003. The server relays the editor + +Status: accepted, 2026-09-23 + +## Context + +Two people edit the same code. Yjs merges concurrent edits in each browser, and it only needs a way to pass messages between them. + +## Decision + +The editor websocket (`app/websocket/yjs.py`) forwards Yjs messages between the people in a room and does not hold the document. It checks each message's framing and rate before forwarding it, answers for an empty document when someone is alone, and records document changes so a room can be replayed. + +## Consequences + +- The server keeps no per-room document in memory and needs no Yjs implementation of its own. +- The live document exists only in the browsers in the room. +- The server cannot check what a change does to the document, only that the message is well formed and within its limits. +- Anything that needs the current code on the server, such as running it without the browser sending it, would need the server to hold the document. diff --git a/docs/decisions/0004-problems-are-migrations.md b/docs/decisions/0004-problems-are-migrations.md new file mode 100644 index 0000000..7a02723 --- /dev/null +++ b/docs/decisions/0004-problems-are-migrations.md @@ -0,0 +1,18 @@ +# 0004. Problems are migrations + +Status: accepted, 2026-09-23 + +## Context + +People outside the project should be able to add problems, and a problem with a wrong test is worse than no problem. + +## Decision + +A problem is one SQL migration that inserts it and one reference solution in `apps/backend/tests/solutions/`. It arrives as a pull request. CI judges the reference solution against every test, and checks that the migration is exactly one `INSERT` of the expected shape, because migrations run on deploy. [CONTRIBUTING.md](../../CONTRIBUTING.md) is the guide. + +## Consequences + +- Every problem is reviewed, and its tests are proven by a solution that passes them. +- Every environment gets the same problems by running the same migrations. +- Hidden tests are public, in the migrations. They keep examples short, but they do not stop someone who reads the repository. +- Changing a problem after it merges takes a new migration. diff --git a/docs/decisions/README.md b/docs/decisions/README.md new file mode 100644 index 0000000..55ffe91 --- /dev/null +++ b/docs/decisions/README.md @@ -0,0 +1,30 @@ +# Decisions + +Each record explains one choice that shapes the system, and why. Records are not edited after they are merged. When a decision changes, add a new record, and change the old one's status line to `Replaced by NNNN` so the history stays readable. + +- [0001](0001-one-host-for-the-backend.md): the API, runner and database share one host; the web app is hosted separately +- [0002](0002-a-container-per-run.md): each submission runs in its own container, under gVisor in production +- [0003](0003-the-server-relays-the-editor.md): the server relays the shared editor and keeps no copy of it +- [0004](0004-problems-are-migrations.md): problems are added by migration, through pull requests + +## Writing one + +Copy this into `NNNN-short-title.md`, numbered after the last record: + +```markdown +# NNNN. Title + +Status: accepted, YYYY-MM-DD + +## Context + +What forced a choice. + +## Decision + +What was chosen. + +## Consequences + +What this makes easy, what it makes hard, and what would make it worth revisiting. +``` diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..bcc5403 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,80 @@ +# Development + +## What you need + +- Docker with Compose v2. Postgres, the API and the runner run in containers, and the runner starts one more container per submission. +- Node 22, the version in `apps/web/.nvmrc` (`nvm use` in `apps/web` picks it up). +- `make`, which macOS and most Linux distributions already have. +- A Clerk application. The free development instance is enough, and in development Clerk supplies the credentials for social sign-in itself. + +## First run + +```bash +make setup # copies both .env templates, installs web dependencies +``` + +Then fill in the two `.env` files it created: + +- `apps/backend/.env`: any `DB_PASSWORD`, `CLERK_ISSUER` (the Frontend API URL under API keys in the Clerk dashboard) and `CLERK_SECRET_KEY`. +- `apps/web/.env`: `VITE_CLERK_PUBLISHABLE_KEY` from the same Clerk instance. + +```bash +make up # Postgres, the API and the runner +make web # the web app, at http://localhost:5173 +``` + +The API applies migrations when it starts, and the runner waits for the API's health check, so the runner never reads a half-migrated schema. On its first start the runner pulls the image it judges submissions in, which takes a minute. + +To try a room with two people, sign in with a second Clerk account in a private window or another browser profile. + +`make` on its own lists every command. The ports are 5173 for the web app, 8080 for the API and 5433 for Postgres, which listens on loopback only. + +## Checks + +```bash +make check # backend tests, web lint, web build +``` + +This is what CI runs (`.github/workflows/`), plus a check that every relative link in the Markdown files resolves. Backend tests run inside the API image against the compose database, in a `tandemcode_test` database that is dropped and recreated on each run. + +## Common changes + +### A schema change + +Add `apps/backend/migrations/V__.sql`, numbered after the highest existing file. Migrations only go forward. Never edit one that has been merged, because production has already applied it; write a new one instead. The API applies pending migrations on start (`app/migrate.py`), and the test suite applies all of them to an empty database, so a broken migration fails CI. + +### An HTTP endpoint + +Requests go from `app/routes/` to `app/services/` to `app/dao/`: + +- The route authenticates with `Depends(current_user_id)` from `app/dependencies.py` and passes the caller's id on. +- The service applies the rules, such as who may do what and rate limits. It receives a user id, never a token. +- The DAO holds the SQL. SQL does not appear anywhere else. + +### A room event + +The server sends events to everyone in a room with `RoomChatManager.broadcast` in `app/websocket/room_chat.py`. The web app handles them in `apps/web/src/hooks/UseWebSocket.ts`. There is one room socket per room: `RoomView` opens it and passes its state to the components that need it. + +### A problem + +See [CONTRIBUTING.md](../CONTRIBUTING.md). A problem is one migration and one reference solution, and CI judges the solution against the problem's tests. + +## Without Docker + +The API and the runner can run from a virtualenv against the compose database: + +```bash +cd apps/backend +python3.11 -m venv .venv && .venv/bin/pip install -r requirements.txt +.venv/bin/uvicorn app.main:app --port 8080 --reload +.venv/bin/python -m app.runner +``` + +The runner still needs Docker to judge submissions. `ALLOW_UNSANDBOXED=1` makes it judge in its own process instead, which is fine for your own code and never for anyone else's. + +## When something goes wrong + +- The runner exits with "SANDBOX_IMAGE is not set". Compose sets it; outside compose, set `SANDBOX_IMAGE=python:3.11-slim`. +- Every API call returns 401. `CLERK_ISSUER` in `apps/backend/.env` and the publishable key in `apps/web/.env` must come from the same Clerk instance. +- The editor reconnects once when a room opens. In development React's strict mode opens each socket twice, and the per-user socket caps in `app/websocket/room_chat.py` can refuse the extra one until the first closes. Production builds open each socket once. +- Your local rooms and users are gone after pulling. The Postgres major version changed. The database volume is named after that version (see `apps/backend/docker-compose.yml`), so a new version starts from an empty database instead of failing on the old data files. The old volume is still there; remove it with `docker volume rm ` once you no longer need it. diff --git a/docs/judge-and-sandbox.md b/docs/judge-and-sandbox.md new file mode 100644 index 0000000..1f37ba0 --- /dev/null +++ b/docs/judge-and-sandbox.md @@ -0,0 +1,33 @@ +# Judge and sandbox + +## The judge + +A problem's tests are a JSON list of `{"input", "expected", "hidden"}`. A submission is a Python program: it reads a test's `input` on stdin and prints its answer. A test passes when the program exits cleanly and its stdout, trimmed at both ends, equals the trimmed `expected`. + +Tests run in order and judging stops at the first failure. The verdict is one of `accepted`, `wrong_answer`, `runtime_error` or `time_limit_exceeded`, with the time taken and a result for each test that ran. For a hidden test the result says only whether it passed: its input, expected output and the program's output are never returned, since a failing program's output can echo the test. + +Hidden tests keep the examples short and stop people writing code for the visible cases only. They are not secret: the migrations that add them are in this repository. + +Each problem sets its own time and memory limit per test. Migration V12 bounds what a problem may ask for. + +The judge itself is `app/runner/judge.py`. It knows nothing about the database, so it can be tested and reused on its own. + +## The sandbox + +People submit code they wrote a minute ago, and anyone can sign up, so every submission is treated as hostile. With `SANDBOX_IMAGE` set, the runner (`app/runner/sandbox.py`) judges each submission in a new container from that image, removed afterwards. The container: + +- has no network +- has a read-only root filesystem, with a small writable `/tmp` +- runs as an unprivileged user with every capability dropped and no way to gain privileges +- has a memory cap, with no swap beyond it, and a limit on processes +- is killed if the whole run outlives its time budget + +Containers share the host's kernel, so a single kernel bug could let a program out. In production each container therefore runs under [gVisor](https://gvisor.dev) (`SANDBOX_RUNTIME=runsc`), which answers the program's system calls in its own kernel written in Go. Getting out then takes a gVisor bug and a kernel bug. `infra/install-gvisor.sh` installs it. + +The runner starts containers through the host's Docker socket, which makes the runner as trusted as the host. Run it on a machine that runs nothing but TandemCode. + +Without `SANDBOX_IMAGE`, the runner refuses to start unless `ALLOW_UNSANDBOXED=1` is set. Then it judges in its own process with resource limits only, which the test suite uses and nothing else should. + +## Reporting a problem with it + +A way out of the sandbox, or a way to see or change other people's runs, is a security issue. Report it privately as described in [SECURITY.md](../SECURITY.md). diff --git a/docs/self-hosting.md b/docs/self-hosting.md new file mode 100644 index 0000000..b5c3407 --- /dev/null +++ b/docs/self-hosting.md @@ -0,0 +1,56 @@ +# Self-hosting + +tandemcode.space runs this way, and you can run your own copy the same way. The API, the runner, Postgres and Caddy share one Linux host. The web app is static files on any host that can send every path to `index.html`. + +## What you need + +- A host running Ubuntu 24.04 with at least 2 GB of memory, reachable on ports 22, 80 and 443. tandemcode.space uses an AWS Lightsail instance. Use a machine that runs nothing else, because the runner controls its Docker daemon (see [judge and sandbox](judge-and-sandbox.md)). +- A domain, with an `A` record for the API's hostname pointing at the host. +- A Clerk production instance for that domain. Clerk lists the DNS records it needs. Social sign-in in production needs your own OAuth credentials for each provider. +- A static host for the web app. `apps/web/vercel.json` configures Vercel, including the security headers. `apps/web/nginx.conf` serves the app from nginx with a shorter set of headers, and has no Content Security Policy beyond refusing to be framed. + +## The API host + +```bash +git clone https://github.com/naman0r/tandemcode.git && cd tandemcode +./infra/bootstrap.sh +``` + +`bootstrap.sh` installs Docker, swap, gVisor and a nightly database dump, then writes `infra/.env` with generated database passwords. Log out and back in once so your user can reach Docker. If the script stopped at its gVisor check the first time, run it again after logging back in. It is safe to rerun. + +Fill in the rest of `infra/.env`. `infra/.env.example` explains each setting. Then start everything: + +```bash +./infra/deploy.sh +``` + +Caddy gets a TLS certificate for `API_DOMAIN` on its own once DNS points at the host. `curl https:///health` should print `{"status":"ok"}`. + +## The web app + +Build `apps/web` with two variables set: `VITE_BACKEND_URL`, the API's `https://` origin, and `VITE_CLERK_PUBLISHABLE_KEY`. Both are baked into the bundle and neither is secret. The site's origins must be listed in `CORS_ORIGINS` in `infra/.env`, because the API refuses tokens minted for any other origin. + +## Checking a deployment + +```bash +make smoke SITE=https:// API=https:// +``` + +This checks that the API is up and refuses anonymous calls and foreign origins, and that the site serves the app with its security headers. Then sign in, open a room with a second account in a private window, and run a solution. + +## Shipping changes + +The web app and the API ship separately: + +- The web app. On Vercel, every push to `main` builds and deploys it. +- The API and runner. Run `./infra/deploy.sh` on the host. It pulls `main`, dumps the database, and rebuilds whatever changed. The API applies new migrations as it starts, and migrations cannot be undone, which is why the dump comes first. + +When a change touches both, deploy the API first, so the new web app never talks to an old API. + +## Backups + +`infra/backup.sh` runs nightly from cron and before every deploy. It writes a gzipped `pg_dump` to `/var/backups/tandemcode` and keeps two weeks of them. Those dumps are on the same disk as the database, so also copy the disk off the host; on Lightsail, turn on automatic snapshots. The restore steps are at the top of `infra/backup.sh`. + +## Moving hosts + +Bootstrap the new host, restore the latest dump into it, run `deploy.sh`, and point the API's `A` record at the new address. From 3a8b3e2505429030b97696ccba171adbbee2c627 Mon Sep 17 00:00:00 2001 From: Naman Rusia Date: Thu, 24 Sep 2026 01:55:06 -0400 Subject: [PATCH 2/3] Give the README a centered header with the logo and status badges The site, API, Vercel deployment, both CI workflows and the license. The API badge reads /health's JSON, because the plain website badge sends HEAD and /health answers GET only. --- README.md | 32 +++++++++++++++++++++++++++++--- docs/assets/logo.png | Bin 0 -> 92908 bytes 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 docs/assets/logo.png diff --git a/README.md b/README.md index 41fd267..4cd5f43 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,34 @@ -# TandemCode +

+ + TandemCode logo + +

-Practice coding problems with a partner. Two people share a room, edit the same code, chat, and run their solution against the problem's tests together. Afterwards the whole session can be replayed. +

TandemCode

-It runs at [tandemcode.space](https://tandemcode.space). It is free and open source under the Apache License 2.0. +

+ Practice coding problems with a partner.
+ One shared editor, one judge, and a replay of the whole session. +

+ +

+ tandemcode.space +  ·  + Docs +  ·  + Add a problem +

+ +

+ Site status + API status + Vercel deployment + Backend tests + Web checks + License +

+ +Two people share a room, edit the same code with live cursors, chat, and run their solution against the problem's tests together. Everyone in the room sees the verdict, and the session can be replayed afterwards. TandemCode is free and open source under the Apache License 2.0. ## What it does diff --git a/docs/assets/logo.png b/docs/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..44aa38dc32ae84f385b6d36bd1f39f87eb55d8a7 GIT binary patch literal 92908 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 >e(;Ax#~pvo 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 literal 0 HcmV?d00001 From 7c286b00052737d3e6780a1fd638a68bbed1e51b Mon Sep 17 00:00:00 2001 From: Naman Rusia Date: Thu, 24 Sep 2026 01:56:22 -0400 Subject: [PATCH 3/3] Draw the CI badges with shields.io to match the rest --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4cd5f43..e9360ea 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ Site status API status Vercel deployment - Backend tests - Web checks + Backend tests + Web checks License