Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ FLAG_MIN_EDIT_EVENTS=10
FLAG_MIN_RESPONSE_LENGTH=200

# Autosave history retention in days (default: 30)
AUTOSAVE_RETENTION_DAYS=30
AUTOSAVE_RETENTION_DAYS=3

# Code execution — custom Go runner
# Deploy runner/ to Render, then set this to your runner's URL
Expand Down
27 changes: 26 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ on:
branches: [main, preview]
push:
branches: [preview]
workflow_dispatch: # allows manual trigger from GitHub Actions tab
workflow_dispatch:
schedule:
- cron: '0 2 * * *' # daily at 2am UTC — runs autosave cleanup

jobs:
build:
name: Build check
runs-on: ubuntu-latest
if: github.event_name != 'schedule'

steps:
- uses: actions/checkout@v4
Expand All @@ -33,3 +36,25 @@ jobs:
NEXTAUTH_URL: https://dbirecoding.vercel.app
RUNNER_URL: https://code-runner-cpqt.onrender.com
RUNNER_API_KEY: dummy

cleanup:
name: Autosave cleanup
runs-on: ubuntu-latest
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Run autosave cleanup
run: npm run cleanup
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
AUTOSAVE_RETENTION_DAYS: 3
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 jvcByte

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
76 changes: 43 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Recoding — Exercise Platform

A controlled environment for running timed coding and writing exercises with live anti-cheat monitoring.
> v1.0.0 · [Live](https://dbirecoding.vercel.app) · [Code Runner](https://code-runner-cpqt.onrender.com)

A controlled environment for running timed coding and writing exercises with live anti-cheat monitoring.

---

Expand All @@ -16,21 +18,37 @@ Instructors can create exercises, upload questions from Markdown files, assign p

| Role | What they do |
|------|-------------|
| Instructor | Creates exercises, uploads questions, assigns participants, sets timing, monitors live activity, reviews submissions |
| Participant | Logs in, sees assigned exercises, answers questions in the editor, submits answers |
| Instructor | Creates exercises, uploads questions, assigns participants, sets timing, monitors live activity, reviews submissions, manages users |
| Participant | Logs in, sees assigned exercises, answers questions in the editor, submits answers, changes password |

---

## Features

- **Timed exercises** — start time, end time, or duration limit per exercise
- **Written questions** — text editor with autosave every 25 seconds
- **Coding drills** — Monaco editor (VS Code engine) with live Go execution via custom runner
- **Question management** — instructors upload `.md` files or add questions manually through the UI
- **Live monitor** — instructors see paste events, focus losses, and keystrokes in real time
- **Anti-cheat** — paste detection, focus-loss tracking, edit event recording, typing replay
- **Audit log** — every instructor action is logged with timestamp
- **CSV export** — download all submissions for an exercise
### Instructor
- Create and manage exercises (title, slug, timing, assignments)
- Upload questions from `.md` files or add manually through the UI
- Enable/disable exercises per session
- Live monitor — see paste events, focus losses, and keystrokes in real time with participant names
- Review submissions with full typing replay, paste events, focus-loss timeline
- Export submissions as CSV
- User management — create accounts, reset passwords, delete participants
- Audit log on all instructor actions
- Search across exercises, submissions, users, and live events

### Participant
- Written questions — text editor with autosave every 25 seconds
- Coding drills — Monaco editor (VS Code engine) with live Go execution
- Navigate between questions, continue from where you left off
- Change password from settings page

### Platform
- Anti-cheat: paste detection, focus-loss tracking, edit event recording
- Timed sessions — start time, end time, or duration limit
- Neon PostgreSQL (serverless, HTTPS)
- Custom Go code runner deployed on Render
- CI/CD: GitHub Actions build check + Vercel preview deployments
- Branch protection: `preview` → `main` requires passing CI

---

Expand All @@ -44,6 +62,7 @@ Instructors can create exercises, upload questions from Markdown files, assign p
| Editor | Monaco Editor |
| Code runner | Custom Go service ([jvcByte/code-runner](https://github.com/jvcByte/code-runner)) |
| Deployment | Vercel (app) + Render (runner) + Neon (database) |
| CI | GitHub Actions |

---

Expand Down Expand Up @@ -81,7 +100,7 @@ npm run seed # seed exercises and default users
npm run import-questions # import questions from docs/ into DB
```

Default accounts created by seed:
Default accounts:
- `instructor` / `instructor123`
- `participant` / `participant123`

Expand All @@ -99,7 +118,7 @@ Open [http://localhost:3000](http://localhost:3000).

Coding drills require the [code-runner](https://github.com/jvcByte/code-runner) service — a lightweight Go HTTP server that compiles and runs participant code.

It's included as a git submodule at `runner/`. Deploy it to Render (free tier):
Deploy to Render (free tier):

1. Go to [render.com](https://render.com) → New → Web Service
2. Connect `github.com/jvcByte/code-runner`
Expand All @@ -119,6 +138,7 @@ It's included as a git submodule at `runner/`. Deploy it to Render (free tier):
| `npm run migrate:fresh` | Drop all tables, re-run migrations, seed, import questions |
| `npm run seed` | Seed exercises and default users |
| `npm run import-questions` | Import questions from docs/ into the database |
| `npm run create-users` | Bulk-create users from docs/users/users.md |
| `npm run cleanup` | Delete autosave history older than 30 days |
| `npm run reset-password <username> <password>` | Reset a user's password |

Expand All @@ -131,24 +151,28 @@ app/
api/ — API route handlers
instructor/ — Instructor dashboard pages
participant/ — Participant session pages
components/ — Shared UI components (Navbar, LogoutButton)
components/ — Shared UI components (Navbar, SearchInput, LogoutButton)
docs/
ascii-art/ — ASCII art coding drills (11 questions)
ascii-art-web/ — ASCII art web coding drills (12 questions)
go-reloaded/ — Go-reloaded written questions (15 questions)
prompt-piscine/— Prompt engineering written questions
banner_files/ — standard.txt, shadow.txt, thinkertoy.txt (injected as stdin)
users/ — users.md with participant credentials
lib/
auth.ts — NextAuth configuration
db.ts — Neon serverless database client
flagging.ts — Anti-cheat flag evaluation
questions.ts — Exercise content loader (reads from DB, falls back to docs/)
questions.ts — Exercise content loader
audit.ts — Audit log helper
rateLimit.ts — Login rate limiter
utils.ts — Shared utility functions (interval parsing, slug conversion, markdown parsing)
migrations/ — SQL migration files (versioned, tracked in schema_migrations table)
utils.ts — Shared utility functions
migrations/ — SQL migration files (versioned)
runner/ — Go code runner (git submodule → jvcByte/code-runner)
scripts/ — CLI utilities (migrate, seed, import-questions, cleanup, reset-password)
scripts/ — CLI utilities
.github/
workflows/
ci.yml — Build check on PRs to main/preview
```

---
Expand All @@ -171,20 +195,6 @@ scripts/ — CLI utilities (migrate, seed, import-questions, cleanup, re

---

## Production checklist

Before going live:

- [ ] Rotate `NEXTAUTH_SECRET` (was in git history)
- [ ] Rotate Neon database password
- [ ] Set `RUNNER_API_KEY` on both Render and Vercel
- [ ] Run `npm run migrate` on production DB
- [ ] Run `npm run import-questions` to populate questions
- [ ] Set up autosave cleanup cron: `0 2 * * * npm run cleanup`
- [ ] Add `Strict-Transport-Security` header for HTTPS enforcement

---

## License

MIT
[MIT](./LICENSE)
Loading