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
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,31 @@ All notable changes to ReadingBat Core are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [3.2.1] - 2026-07-03

A maintenance release: a Gradle 9.6.1 upgrade, a routine dependency refresh, and two build/test polish items. No functional changes to the running server.

### Changed

- Reworked the `configureVersions()` pre-release filter in the root `build.gradle.kts`: a candidate is now rejected only when the *current* version is stable, so dependencies intentionally tracked on a pre-release line (e.g. the detekt 2.0 alpha) still surface newer pre-releases. The qualifier regex now matches both dash-style (`-alpha`) and dot-style (Netty's `.Beta1`) suffixes while leaving stable classifiers like `-jre` / `.Final` / `-macos` alone
- Marked the `dependencyUpdates` task incompatible with the configuration cache so `make versions` no longer trips the cache
- `TestSupport.forEachAnswer` now accepts a `suspend` block, matching the suspend `functionInfo()` call site introduced in 3.2.0
- Bumped version to 3.2.1

### Dependencies

- Gradle wrapper 9.5.1 → 9.6.1
- common-utils 2.9.2 → 2.9.3
- Ktor 3.5.0 → 3.5.1
- Exposed 1.3.0 → 1.3.1
- Kotest 6.2.0 → 6.2.1
- Flyway 12.8.1 → 12.10.0
- PostgreSQL driver 42.7.11 → 42.7.12
- Google Cloud SQL socket factory 1.28.4 → 1.28.6
- Playwright 1.60.0 → 1.61.0
- detekt 2.0.0-alpha.4 → 2.0.0-alpha.5
- Vanniktech maven-publish 0.36.0 → 0.37.0

## [3.2.0] - 2026-06-15

A security-hardening release. A multi-agent security review surfaced 48 confirmed findings (7 high, 19 medium, 22 low); all 48 are addressed here, alongside the build/tooling cleanup below.
Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- Run a single test by name: `./gradlew :readingbat-core:test --tests "EndpointTest.Simple endpoint tests"`
- Run application: `make run` or `./gradlew run`

Gradle 9.5.0 with `org.gradle.parallel=true` and `org.gradle.configuration-cache=true` enabled by default. The version
Gradle 9.6.1 with `org.gradle.parallel=true` and `org.gradle.configuration-cache=true` enabled by default. The version
catalog (`gradle/libs.versions.toml`) is the single source of truth for plugin, dependency, **and toolchain** versions —
the `gradle-wrapper` and `jvm` keys are read by `build.gradle.kts` (via `libs.versions.jvm`) and by the Makefile (the
`upgrade-wrapper` target derives `GRADLE_VERSION` from the `gradle-wrapper` key in the catalog). Project version comes from `gradle.properties`
Expand Down Expand Up @@ -159,7 +159,7 @@ The `readingbat-kotest` module provides `TestSupport` with helpers:

### Key Dependencies

- **common-utils** 2.9.2 (BOM from `com.github.pambrose`): shared utility library providing core-utils, email-utils,
- **common-utils** 2.9.3 (BOM from `com.github.pambrose`): shared utility library providing core-utils, email-utils,
exposed-utils, ktor-client/server-utils, script-utils, etc. (`respondWith`/`redirectTo` take a `suspend` block as of 2.9.2)
- **prometheus-proxy** 3.2.0: metrics collection
- **Kover** 0.9.8: code coverage, applied to every subproject and aggregated at the root; CI uploads
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ A Kotlin-based framework for creating interactive programming challenges and edu

ReadingBat Core is built using modern Kotlin technologies:

- **Web Framework**: Ktor 3.5.0 with CIO engine
- **Web Framework**: Ktor 3.5.1 with CIO engine
- **Database**: PostgreSQL with Exposed ORM (`exposed-kotlin-datetime`) and HikariCP connection pooling
- **Authentication**: OAuth (GitHub, Google, verified-email required) with signed + encrypted session cookies
- **Script Execution**: JSR-223 scripting engines for safe code evaluation
- **Build System**: Gradle 9.5 with Kotlin DSL, multi-module structure, and configuration cache enabled
- **Build System**: Gradle 9.6 with Kotlin DSL, multi-module structure, and configuration cache enabled
- **Serialization**: kotlinx.serialization for JSON processing
- **Testing**: Kotest framework with Playwright for E2E testing

Expand Down
18 changes: 18 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Release Notes

## v3.2.1 — 2026-07-03

Maintenance release. A Gradle 9.6.1 upgrade, a routine dependency refresh, and two small build/test polish items. No functional changes to the running server, and no configuration or upgrade steps are required — this is a drop-in bump from 3.2.0.

### Highlights

- **Gradle 9.6.1.** The wrapper moves from 9.5.1 to 9.6.1.
- **Smarter pre-release version filter.** `configureVersions()` now rejects a pre-release candidate only when the *current* dependency is stable, so libraries deliberately tracked on a pre-release line (e.g. the detekt 2.0 alpha) keep surfacing newer pre-releases in `make versions`. The qualifier regex now catches both dash-style (`-alpha`) and dot-style (Netty's `.Beta1`) suffixes while leaving stable classifiers like `-jre` / `.Final` / `-macos` alone, and the `dependencyUpdates` task is marked incompatible with the configuration cache.
- **`TestSupport.forEachAnswer` takes a `suspend` block**, matching the suspend `functionInfo()` call site introduced in 3.2.0.

### Dependencies

Gradle 9.5.1 → 9.6.1 · common-utils 2.9.2 → 2.9.3 · Ktor 3.5.0 → 3.5.1 · Exposed 1.3.0 → 1.3.1 · Kotest 6.2.0 → 6.2.1 · Flyway 12.8.1 → 12.10.0 · PostgreSQL driver 42.7.11 → 42.7.12 · Cloud SQL socket factory 1.28.4 → 1.28.6 · Playwright 1.60.0 → 1.61.0 · detekt 2.0.0-alpha.4 → 2.0.0-alpha.5 · maven-publish 0.36.0 → 0.37.0

**Full Changelog**: https://github.com/readingbat/readingbat-core/compare/3.2.0...3.2.1

---

## v3.2.0 — 2026-06-15

Security-hardening release. A multi-agent security review surfaced 48 confirmed findings (7 high, 19 medium, 22 low); all 48 are addressed here. The headline items close an authentication bypass, an RCE, two IDOR/authorization gaps, and stored/reflected XSS, plus a batch of WebSocket and caching reliability fixes. The 3.1.9-era build/tooling cleanup ships in the same release.
Expand Down
23 changes: 17 additions & 6 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@

import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask
import com.vanniktech.maven.publish.JavadocJar
import com.vanniktech.maven.publish.SourcesJar
import dev.detekt.gradle.Detekt
import dev.detekt.gradle.extensions.DetektExtension
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.gradle.kotlin.dsl.withType

plugins {
alias(libs.plugins.kotlin.jvm)
Expand Down Expand Up @@ -201,13 +203,22 @@ fun Project.configureTesting() {
}

fun Project.configureVersions() {
// Match preview/unstable qualifiers anchored on a separator so plain substrings like
// "DEV" inside a real version (e.g. "1.0-developer") don't trigger false rejections.
val nonStableRegex = Regex("(?i)[-.](RC|BETA|ALPHA|M\\d+|SNAPSHOT|DEV|PREVIEW|EAP|CR)\\b")

tasks.withType<com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask>().configureEach {
// A pre-release qualifier is a `.` or `-` delimiter followed by a known unstable
// keyword. `m\d` matches milestones (`-M1`/`.M2`) without catching stable classifiers
// like `-macos`/`-MR1`, and the `[.-]` delimiter catches both dash-style (`-alpha`)
// and dot-style (Netty's `.Beta1`) qualifiers while leaving `-jre`/`.Final` stable.
val preReleaseQualifier =
Regex("""[.-](rc|beta|alpha|m\d|cr|snapshot|eap|dev|milestone|pre)""", RegexOption.IGNORE_CASE)

fun isNonStable(version: String): Boolean = preReleaseQualifier.containsMatchIn(version)

tasks.withType<DependencyUpdatesTask>().configureEach {
notCompatibleWithConfigurationCache("the dependency updates plugin is not compatible with the configuration cache")
// Reject a pre-release candidate only when the current version is stable. For
// dependencies we intentionally track on a pre-release line (e.g. a detekt
// alpha), newer pre-releases are still surfaced as available updates.
rejectVersionIf {
nonStableRegex.containsMatchIn(candidate.version)
isNonStable(candidate.version) && !isNonStable(currentVersion)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group=com.readingbat
version=3.2.0
version=3.2.1

kotlin.code.style=official
org.gradle.jvmargs=-Xmx8g -Dfile.encoding=UTF-8
Expand Down
22 changes: 11 additions & 11 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
[versions]
# Toolchain versions
gradle-wrapper = "9.5.1"
gradle-wrapper = "9.6.1"
jvm = "17"

# Plugin versions
buildconfig = "6.0.10"
detekt = "2.0.0-alpha.4"
detekt = "2.0.0-alpha.5"
kotlin = "2.4.0"
kotlinter = "5.5.0"
kover = "0.9.8"
dokka = "2.2.0"
maven-publish = "0.36.0"
maven-publish = "0.37.0"
versions = "0.54.0"

# Library versions
cloud = "1.28.4"
cloud = "1.28.6"
commons = "1.15.0"
exposed = "1.3.0"
exposed = "1.3.1"
flexmark = "0.64.8"
flyway = "12.8.1"
flyway = "12.10.0"
github-api = "1.330"
hikari = "7.1.0"
java-scriptengine = "2.0.0"
khealth = "3.0.1"
kotest = "6.2.0"
ktor = "3.5.0"
kotest = "6.2.1"
ktor = "3.5.1"
logback = "1.5.18"
logging = "7.0.12"
pgjdbc = "0.8.9"
playwright = "1.60.0"
postgres = "42.7.11"
playwright = "1.61.0"
postgres = "42.7.12"
prometheus = "0.16.0"
prometheus-proxy = "3.2.0"
python = "2.7.4"
resend = "4.13.0"
serialization = "1.11.0"
testcontainers = "1.21.4"
utils = "2.9.2"
utils = "2.9.3"

[libraries]
# Serialization
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
Expand Down
4 changes: 2 additions & 2 deletions gradlew

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

4 changes: 2 additions & 2 deletions gradlew.bat

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

8 changes: 4 additions & 4 deletions llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ ReadingBat Core is a web application built with Ktor that serves programming cha

## Key Technologies

- Kotlin 2.4.0, Ktor 3.5.0 (CIO engine), Exposed ORM 1.3.0 with kotlinx-datetime, PostgreSQL
- Kotlin 2.4.0, Ktor 3.5.1 (CIO engine), Exposed ORM 1.3.1 with kotlinx-datetime, PostgreSQL
- Kotlinx.html for server-side HTML generation (no templates)
- Kotest 6.2.0 for testing, Playwright for E2E tests
- Gradle 9.5.1 multi-module build with version catalog (libs.versions.toml) as the single source of truth for plugin, dependency, and toolchain (`gradle`, `jvm`) versions; parallel project execution and configuration cache enabled
- Kotest 6.2.1 for testing, Playwright for E2E tests
- Gradle 9.6.1 multi-module build with version catalog (libs.versions.toml) as the single source of truth for plugin, dependency, and toolchain (`gradle`, `jvm`) versions; parallel project execution and configuration cache enabled
- Kover 0.9.8 for code coverage, uploaded to Codecov from CI (per-area components defined in `codecov.yml`)
- Detekt 2.0 alpha (`dev.detekt` plugin) for static analysis; Kotlinter for ktlint style
- common-utils 2.9.2 (shared utility BOM from `com.github.pambrose`)
- common-utils 2.9.3 (shared utility BOM from `com.github.pambrose`)
- Java 17 toolchain

## Project Structure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ object TestSupport {

fun FunctionInfo.answerFor(index: Int) = ChallengeAnswer(this, index)

suspend fun Challenge.forEachAnswer(block: (ChallengeAnswer) -> Unit) =
suspend fun Challenge.forEachAnswer(block: suspend (ChallengeAnswer) -> Unit) =
functionInfo().apply {
(0 until questionCount).toList().forAll { i -> block(ChallengeAnswer(this, i)) }
}
Expand Down
16 changes: 16 additions & 0 deletions website/readingbat-core/docs/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ icon: lucide/tag

For the complete, commit-level history see [`CHANGELOG.md`](https://github.com/readingbat/readingbat-core/blob/master/CHANGELOG.md) in the repository.

## v3.2.1 — 2026-07-03

Maintenance release: a Gradle 9.6.1 upgrade, a routine dependency refresh, and two small build/test polish items. No functional changes to the running server and no upgrade steps — a drop-in bump from 3.2.0.

### Changed

- **Gradle 9.6.1** — the wrapper moves from 9.5.1 to 9.6.1.
- **Smarter pre-release version filter** — `configureVersions()` rejects a pre-release candidate only when the *current* dependency is stable, so libraries tracked on a pre-release line (e.g. the detekt 2.0 alpha) keep surfacing newer pre-releases. The `dependencyUpdates` task is also marked incompatible with the configuration cache.
- **`TestSupport.forEachAnswer` takes a `suspend` block** — matching the suspend `functionInfo()` call site introduced in 3.2.0.

### Dependencies

Gradle 9.5.1 → 9.6.1 · common-utils 2.9.2 → 2.9.3 · Ktor 3.5.0 → 3.5.1 · Exposed 1.3.0 → 1.3.1 · Kotest 6.2.0 → 6.2.1 · Flyway 12.8.1 → 12.10.0 · PostgreSQL driver 42.7.11 → 42.7.12 · Cloud SQL socket factory 1.28.4 → 1.28.6 · Playwright 1.60.0 → 1.61.0 · detekt 2.0.0-alpha.4 → 2.0.0-alpha.5 · maven-publish 0.36.0 → 0.37.0

[Full changelog: 3.2.0…3.2.1](https://github.com/readingbat/readingbat-core/compare/3.2.0...3.2.1)

## v3.2.0 — 2026-06-15

Security-hardening release. A multi-agent security review surfaced 48 confirmed findings (7 high, 19 medium, 22 low); all 48 are addressed here, alongside a batch of WebSocket/caching reliability fixes and the 3.1.9-era build/tooling cleanup.
Expand Down
Loading