Skip to content

Repository files navigation

JudgeMyCode

JudgeMyCode is a React/Vite interview workspace backed by a Go API and PostgreSQL. The supported local workflow runs PostgreSQL in Docker and runs the API and frontend directly on the host for fast reloads.

One-command local development

Prerequisites:

  • Go 1.25 or newer compatible toolchain
  • Node.js 22.12+ and npm
  • Docker with Compose v2
  • curl, lsof, and cksum (included by default on macOS and most Unix systems)
  • For every local execution language: Python 3, a JDK (javac/java), and a C++17 compiler (g++). Missing toolchains do not prevent the application from starting; that language reports RUNTIME_UNAVAILABLE when used.

From this directory:

./run-local.sh

The command is safe to repeat. It creates missing local environment defaults, starts and waits for PostgreSQL, applies migrations, explicitly loads the local demo users and problem catalog, installs locked frontend dependencies when needed, rebuilds/restarts the API and Vite processes, and waits for both HTTP endpoints. The explicit restart prevents a previous binary from serving stale source or configuration.

Yes: run-local.sh starts the database dependency, backend, and frontend. To start again after stopping—or to rebuild/restart after code changes—run the same command:

./run-local.sh

Use ./run-local.sh --setup-only when you want dependencies, migrations, seeds, and npm packages prepared without starting the API or frontend.

Service Local address
Frontend http://127.0.0.1:5173
API http://127.0.0.1:5050/api
PostgreSQL 127.0.0.1:5432

Runtime logs are under logs/; validated PID files are backend.pid and frontend.pid.

./stop-local.sh                 # API + frontend
./stop-local.sh --dependencies  # also stop PostgreSQL; data volume is kept

The Makefile exposes the same workflow:

make setup     # dependencies, database, migrations, local seeds
make dev       # complete local stack
make stop      # application processes only
make stop-all  # application + PostgreSQL
make check     # shell, Go, TypeScript, and Compose checks
make test      # Go tests and race detector
make build     # API binary and production frontend bundle

Repository layout

  • interviewhub-backend-go/: Go API with internal/httpapi as the composition/router boundary, embedded SQL migrations, PostgreSQL adapter, and local execution engine.
  • interviewhub-lld/: React 19, TypeScript, Vite, and Monaco frontend organized around src/app, feature modules under src/features, and shared infrastructure under src/shared.
  • run-local.sh / stop-local.sh: idempotent local lifecycle.
  • .github/workflows/ci.yml: backend, frontend, script, Compose, and image checks.

Execution is asynchronous: run/submit returns an execution ID, and the client polls the owned execution resource until it reaches COMPLETED, FAILED, or TIMED_OUT.

Workspace autosave uses server revisions instead of timestamps. Every write is compare-and-swap; a stale browser receives 409 Conflict and must explicitly keep its local draft or load the server version. Each open tab also keeps its own recovery journal, so tabs cannot silently overwrite one another's unsaved work.

Administrator problem edits also use compare-and-swap with the problem's updatedAt revision. The guarded statement update and starter/test replacement are one PostgreSQL transaction, and catalog seed/reset operations share the same mutation lock. A stale editor therefore receives 409 Conflict instead of silently replacing another administrator's work.

A plain run executes once with custom standard input. A selected public test runs with its server-owned input and expected output, “Run all tests” evaluates all public tests, and submit evaluates public plus hidden tests before writing submission history. Client-supplied assertions are never trusted.

Submit jobs capture an immutable catalog/test snapshot at queue admission and persist its SHA-256 evaluationRevision. Later administrator edits therefore cannot change an in-flight grade, and historical assertion values are removed from submission responses.

Submission history uses owner-scoped keyset pagination (50 rows by default, 100 maximum) and lightweight indexed summaries; source files and execution output are loaded only through the owner/admin detail endpoint. User progress, including solved problem IDs, is calculated in one PostgreSQL aggregate rather than by downloading and scanning a tenant's history in the browser.

Refresh credentials rotate once, are serialized with logout at the database family boundary, and retain the original absolute expiry. The browser uses a cross-tab lock plus principal/login-epoch lineage, so concurrent tabs adopt one replacement and a delayed request can never replay under a newly signed-in account. Failed logouts are kept as independent per-credential records in a bounded, deduplicated revocation queue, so concurrent tabs cannot lose one another's work; the queue is retried at startup, when connectivity returns, on cross-tab changes, and around later sign-ins. One required browser Web Lock serializes every credential mutation; unsupported browsers fail closed instead of relying on an expiring client lease. A separate drain lock keeps old network revocations from blocking a new login, and each HTTP request carries the bearer captured with its originating session and body. The API bounds refresh and logout requests independently by source and hashed opaque credential, and PostgreSQL family operations use the direct family_id index.

AI feedback is optional. Configure an OpenAI-compatible chat-completions endpoint with AI_API_URL, AI_API_KEY, and AI_MODEL; AI_REQUEST_TIMEOUT defaults to 20s and AI_MAX_OUTPUT_TOKENS to 700. With no key/provider configured, the API returns a clear unavailable/configuration error and never fabricates feedback. Staging/production also requires AI_EXTERNAL_GUARD=true as an explicit acknowledgement that a distributed quota and spend guard exists upstream.

Security boundary

EXECUTION_ENABLED=true is written only for the explicit local-development workflow. The current runner executes candidate programs on the API host and is not a security sandbox. Never expose it to untrusted users. Production must set EXECUTION_ENABLED=false until a dedicated network-disabled judge service with CPU, memory, process, filesystem, output, and wall-time isolation is implemented.

The Compose file intentionally contains PostgreSQL only. Redis and the placeholder worker were removed because no durable queue/worker implementation exists yet.

See backend documentation, API documentation, and the production architecture contract.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages