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 .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: "22"
node-version: "26"
cache: npm
cache-dependency-path: web/package-lock.json
- run: npm ci
Expand Down
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ All notable changes are documented here. The format follows [Keep a Changelog](h
### Added

- First public version: about 4,100 problems (2,830 runnable against 274k hidden tests), company frequency lists for 423 companies, reference solutions with explanations.
- Judging in Python 3.14, Java 25, C++23 (Clang 19) and Kotlin 2.4 in a sandboxed runner with no network access.
- Judging in Python 3.14, Java 25, C++23 (Clang 23) and Kotlin 2.4 in a sandboxed runner with no network access.
- Problem list, company pages, workspace with Run/Submit and custom cases, submission history, progress dashboard and export.
- One-command setup with Docker Compose; content imported from open datasets at first run, with mirror fallbacks.
- Repo-kept content in `content/`: new problems and extra solutions, tests or corrections for existing ones, checked in CI by `make validate-content` and marked "local" in the app.
- The Progress page lists every solved problem, with when it was first accepted and in which languages; the solved counts link to the filtered problem list.
- **Refresh content** never removes problems, solutions or test cases that an earlier import had.

### Changed

- Dependencies brought up to date: Clang 23 from LLVM's apt repository (was Debian's Clang 19), Node 26 LTS for the web build and CI (was 22), Gson 2.15, TanStack Query 5.105.1. The excluded test cases were regenerated with the new toolchain. TypeScript stays on 5.9 until openapi-typescript and typescript-eslint support 7.

### Fixed

- `LOCALCODE_ALLOWED_HOSTS` set when starting Docker Compose now reaches the app, so it can be served under another host name as the README describes.
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Everyone taking part is expected to follow the [Code of Conduct](CODE_OF_CONDUCT

## Getting set up

You need Docker (with Compose v2), Python 3.14, Node 22 and `make`.
You need Docker (with Compose v2), Python 3.14, Node 26 and `make`.

```bash
git clone https://github.com/RyPope/localcode.git && cd localcode
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ flowchart LR
B["Browser<br/>localhost:4173"] --> A
subgraph Docker["Docker Compose"]
A["app<br/>FastAPI + React UI"]
R["runner<br/>Python 3.14 · JDK 25 · Clang 19 · Kotlin 2.4<br/>no network"]
R["runner<br/>Python 3.14 · JDK 25 · Clang 23 · Kotlin 2.4<br/>no network"]
D[("localcode-data volume<br/>content.db · user.db")]
A -- "code + test inputs<br/>(Unix socket)" --> R
R -- "raw outputs" --> A
Expand Down Expand Up @@ -162,7 +162,7 @@ docker compose cp app:/data/user.db ./localcode-user-backup.db
- **Kotlin reference solutions are sparse upstream**, so the Solutions tab shows Java for most Kotlin problems. Kotlin submissions are judged normally.
- **Problems with several valid answers** are judged by checking the answer, not by matching one expected output: 75 problems ("return any valid arrangement", course orders, Gray codes, CIDR covers, …) have a checker that validates the answer against the input, and "in any order" answers are compared ignoring order (at every level where the problem allows it). A multi-answer problem without a checker yet is still compared against one expected answer; please report it.
- **Design, SQL, shell and concurrency problems** can be read but not run.
- **C++ is compiled with Clang 19 and `-std=c++23 -O2`** but without AddressSanitizer, so some out-of-bounds bugs may go unnoticed instead of failing with a runtime error.
- **C++ is compiled with Clang 23 and `-std=c++23 -O2`** but without AddressSanitizer, so some out-of-bounds bugs may go unnoticed instead of failing with a runtime error.
- **Cold-start compile times** are about 1 to 2 s for Java and C++ and about 4 s for Kotlin.

## Troubleshooting
Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The app has no login, so it defends against other web pages instead:
## Supply chain

- Dependencies are pinned, and Dependabot proposes updates.
- Toolchain downloads in the runner image (Kotlin, Gson) are verified against pinned SHA-256 checksums.
- Toolchain downloads in the runner image (Kotlin, Gson) are verified against pinned SHA-256 checksums, and the LLVM apt repository that provides Clang is trusted only through its signing key, itself pinned by checksum.
- CI actions are pinned to commit SHAs.
- Problem content is downloaded at runtime from the configured sources over HTTPS. It is rendered only after sanitisation, and the reference solutions it contains are only ever executed inside the sandbox.

Expand Down
2 changes: 1 addition & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build context: repository root.
FROM node:22.23.4-slim AS web
FROM node:26.13.0-trixie-slim AS web
WORKDIR /web
COPY web/package.json web/package-lock.json ./
RUN npm ci --no-audit --no-fund
Expand Down
9 changes: 5 additions & 4 deletions backend/localcode/data/excluded_cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -553,9 +553,7 @@
],
"construct-string-with-minimum-cost-easy": [],
"construct-string-with-repeat-limit": [],
"construct-target-array-with-multiple-sums": [
"e87c1970e8e58b6d"
],
"construct-target-array-with-multiple-sums": [],
"construct-the-lexicographically-largest-valid-sequence": [],
"construct-the-longest-new-string": [],
"construct-the-minimum-bitwise-array-i": [],
Expand Down Expand Up @@ -752,7 +750,9 @@
"count-pairs-of-connectable-servers-in-a-weighted-tree-network": [],
"count-pairs-of-equal-substrings-with-minimum-difference": [],
"count-pairs-of-nodes": [],
"count-pairs-of-points-with-distance-k": [],
"count-pairs-of-points-with-distance-k": [
"72a3d1416e865fc1"
],
"count-pairs-of-similar-strings": [],
"count-pairs-that-form-a-complete-day-i": [],
"count-pairs-that-form-a-complete-day-ii": [],
Expand Down Expand Up @@ -5154,6 +5154,7 @@
"verify-preorder-sequence-in-binary-search-tree": [],
"verify-preorder-serialization-of-a-binary-tree": [],
"verifying-an-alien-dictionary": [
"2fbe222adff16def",
"3ce6e99bf3f83090",
"63c7a7a504c252b0",
"6574a41a9623530d",
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Each runner replica serves HTTP on `/run/localcode/runner-<host>.sock` (mode 066
|---|---|---|
| Python | `harness/py_driver.py` | Converts arguments using `params` types; per-case stdout capture; 128 MB thread stack |
| Java / Kotlin | `harness/jvm/Driver.java` | Reflection over the `Solution` method's generic types; Gson; `javafx.util.Pair` provided |
| C++ | `harness/cpp_gen.py` + `cpp/lc.hpp` | Clang 19, `-std=c++23 -O2` (as LeetCode); generated `main` from the C++ signature; precompiled prelude and JSON I/O object; stdout captured at the file-descriptor level |
| C++ | `harness/cpp_gen.py` + `cpp/lc.hpp` | Clang 23, `-std=c++23 -O2`; generated `main` from the C++ signature; precompiled prelude and JSON I/O object; stdout captured at the file-descriptor level |

Limits are defined once in `config.Limits` and sent with every request: Run gets 2 s per case and Submit 10 s in total, plus a per-language start-up allowance; memory is 1 GiB, applied as an address-space limit (Python, C++) or a heap of 75% of it (JVM). Output files are capped and the sandbox user is limited to 256 processes.

Expand Down
19 changes: 15 additions & 4 deletions runner/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
# Pinned toolchains: every localcode user judges against exactly these versions.
FROM python:3.14.10-slim-trixie AS runtime

# Clang comes from LLVM's own apt repository (Debian's is a few majors behind). Its signing key is
# pinned by checksum; the fingerprint is 6084F3CF814B57C1CF12EFD515CF4D18AF4F7421.
ARG CLANG_MAJOR=23
ARG LLVM_KEY_SHA256=8b2a587ffd672c4687e7581dad4b2f6c1bb2ad6b480cd9771ba2ff48e0b8c75d
RUN apt-get update \
&& apt-get install -y --no-install-recommends clang g++ nlohmann-json3-dev curl unzip ca-certificates \
&& apt-get install -y --no-install-recommends curl ca-certificates \
&& curl -fsSL -o /etc/apt/keyrings/llvm.asc https://apt.llvm.org/llvm-snapshot.gpg.key \
&& echo "${LLVM_KEY_SHA256} /etc/apt/keyrings/llvm.asc" | sha256sum -c - \
&& echo "deb [signed-by=/etc/apt/keyrings/llvm.asc] https://apt.llvm.org/trixie/ llvm-toolchain-trixie-${CLANG_MAJOR} main" \
> /etc/apt/sources.list.d/llvm.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends clang-${CLANG_MAJOR} g++ nlohmann-json3-dev unzip \
&& ln -s /usr/bin/clang++-${CLANG_MAJOR} /usr/local/bin/clang++ \
&& rm -rf /var/lib/apt/lists/*

COPY --from=eclipse-temurin:25.0.5_8-jdk /opt/java/openjdk /opt/java
Expand All @@ -15,8 +26,8 @@ RUN curl -fsSL -o /tmp/k.zip https://github.com/JetBrains/kotlin/releases/downlo
&& echo "${KOTLIN_SHA256} /tmp/k.zip" | sha256sum -c - \
&& unzip -q /tmp/k.zip -d /opt && rm /tmp/k.zip

ARG GSON_VERSION=2.11.0
ARG GSON_SHA256=57928d6e5a6edeb2abd3770a8f95ba44dce45f3b23b7a9dc2b309c581552a78b
ARG GSON_VERSION=2.15.0
ARG GSON_SHA256=96d3dd843dc2911de01cdabcd50064cb9e860353102a0a78c96fd833d396fc7d
RUN mkdir -p /opt/lib \
&& curl -fsSL -o /opt/lib/gson.jar https://repo1.maven.org/maven2/com/google/code/gson/gson/${GSON_VERSION}/gson-${GSON_VERSION}.jar \
&& echo "${GSON_SHA256} /opt/lib/gson.jar" | sha256sum -c -
Expand All @@ -31,7 +42,7 @@ RUN mkdir -p /tmp/drv \
&& javac -cp /opt/lib/gson.jar -d /tmp/drv harness/jvm/Driver.java harness/jvm/javafx/util/Pair.java \
&& jar cf /opt/lib/driver.jar -C /tmp/drv . && rm -rf /tmp/drv

# C++ is compiled with Clang (as LeetCode does) against libstdc++ (installed with g++).
# C++ is compiled with Clang against libstdc++ (installed with g++).
# Precompiled prelude; flags must match CPP_FLAGS in languages.py.
RUN mkdir -p /opt/lc && cp harness/cpp/lc.hpp harness/cpp/lc_io.cpp /opt/lc/ \
&& clang++ -std=c++23 -O2 -w -x c++-header /opt/lc/lc.hpp -o /opt/lc/lc.hpp.pch \
Expand Down
24 changes: 12 additions & 12 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"@fontsource/geist-mono": "^5.3.0",
"@fontsource/geist-sans": "^5.3.0",
"@monaco-editor/react": "4.7.0",
"@tanstack/react-query": "5.105.0",
"@tanstack/react-query": "5.105.1",
"dompurify": "^3.4.17",
"katex": "^0.19.1",
"marked": "18.1.2",
Expand All @@ -37,7 +37,7 @@
"eslint": "^10.14.0",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.7",
"globals": "^17.13.0",
"globals": "^17.14.0",
"openapi-typescript": "^7.13.0",
"playwright": "^1.64.1",
"prettier": "^3.9.10",
Expand Down