From 2811b748177f2c1e62ef58c28b51d97aa0244275 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 15 Oct 2026 00:57:16 +0000 Subject: [PATCH 1/2] ci: add Rust MSRV and latest-stable quick checks Declare rust-version = "1.89.0" in the workspace and inherit it in every package. Next to the full test matrix on the pinned toolchain from rust-toolchain.toml, add two quick checks that need no PostgreSQL or credentials: - Quick check (Rust MSRV) reads rust-version from Cargo.toml and builds the production binary on it with the committed lockfile. - Quick check (Rust stable) runs fmt and Clippy on the latest stable release, to flag breakage before the pin is bumped. Document the three toolchains and how to bump the pin or the MSRV in DEVELOPMENT.md. Refs CIP-4954 Claude-Session: https://claude.ai/code/session_01PeBRsmwf2siZczh49FAPfe --- .github/workflows/test.yml | 85 +++++++++++++++++++ CHANGELOG.md | 2 + Cargo.toml | 4 + DEVELOPMENT.md | 37 ++++++++ packages/cipherstash-proxy-burn-in/Cargo.toml | 1 + .../cipherstash-proxy-integration/Cargo.toml | 1 + packages/cipherstash-proxy/Cargo.toml | 1 + packages/eql-mapper-macros/Cargo.toml | 1 + packages/eql-mapper/Cargo.toml | 1 + packages/showcase/Cargo.toml | 1 + 10 files changed, 134 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 276727f38..464c81e52 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -67,6 +67,91 @@ jobs: channel: engineering webhook_url: ${{ secrets.SLACK_NOTIFICATION_WEBHOOK_URL }} + # Quick checks outside the pinned toolchain. Neither needs PostgreSQL, + # credentials, or the test matrix. + # + # MSRV: builds the production binary on `rust-version` from Cargo.toml, so a + # change that raises the compiler requirement fails here. + msrv: + name: Quick check (Rust MSRV) + runs-on: blacksmith-16vcpu-ubuntu-2204 + timeout-minutes: 30 + + steps: + - uses: actions/checkout@v4 + + - name: Read MSRV from Cargo.toml + id: msrv + shell: /bin/bash -l {0} + run: | + set -euo pipefail + # Read the root manifest directly: cargo itself would need the + # rust-toolchain.toml toolchain installed first. + msrv=$(sed -n 's/^rust-version = "\(.*\)"$/\1/p' Cargo.toml) + if [[ -z "${msrv}" ]]; then + echo "::error::Cargo.toml [workspace.package] has no rust-version" + exit 1 + fi + echo "MSRV: ${msrv}" + echo "version=${msrv}" >> "$GITHUB_OUTPUT" + + - name: Install Rust ${{ steps.msrv.outputs.version }} + shell: /bin/bash -l {0} + run: rustup toolchain install "${{ steps.msrv.outputs.version }}" --profile minimal --no-self-update + + - name: Setup Rust cache + uses: Swatinem/rust-cache@v2 + with: + key: msrv-${{ steps.msrv.outputs.version }} + + - name: Build production binary + shell: /bin/bash -l {0} + env: + # Overrides rust-toolchain.toml. + RUSTUP_TOOLCHAIN: ${{ steps.msrv.outputs.version }} + run: | + set -euo pipefail + rustc --version + declared=$(cargo metadata --no-deps --format-version 1 \ + | jq -r '.packages[] | select(.name == "cipherstash-proxy") | .rust_version') + if [[ "${declared}" != "${{ steps.msrv.outputs.version }}" ]]; then + echo "::error::cipherstash-proxy rust-version is '${declared}', expected '${{ steps.msrv.outputs.version }}'" + exit 1 + fi + cargo build --locked --release --package cipherstash-proxy + + # Latest stable: early warning that a new Rust release breaks the build or + # adds Clippy lints, before the pinned toolchain is bumped to it. + stable: + name: Quick check (Rust stable) + runs-on: blacksmith-16vcpu-ubuntu-2204 + timeout-minutes: 30 + env: + # Overrides rust-toolchain.toml. + RUSTUP_TOOLCHAIN: stable + + steps: + - uses: actions/checkout@v4 + + - name: Install latest stable Rust + shell: /bin/bash -l {0} + run: | + rustup toolchain install stable --profile minimal --component clippy,rustfmt --no-self-update + rustc --version + + - name: Setup Rust cache + uses: Swatinem/rust-cache@v2 + with: + key: stable + + - name: Check formatting + shell: /bin/bash -l {0} + run: cargo fmt --all -- --check + + - name: Clippy + shell: /bin/bash -l {0} + run: cargo clippy --locked --all --no-deps --all-targets --all-features -- -D warnings + burn-in: name: Encrypted burn-in (PostgreSQL 17) runs-on: blacksmith-16vcpu-ubuntu-2204 diff --git a/CHANGELOG.md b/CHANGELOG.md index b5aa3bdb6..fa138cffb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Changed +- **Minimum supported Rust version**: building Proxy from source now requires Rust 1.89.0 or later, declared as `rust-version` in `Cargo.toml` so Cargo reports an older compiler clearly instead of failing deep in a dependency. CI builds the production binary on Rust 1.89.0 to keep that minimum from rising by accident. Development, tests, and release binaries use the Rust version pinned in `rust-toolchain.toml` (currently 1.99.0). See [Supported Rust versions](DEVELOPMENT.md#supported-rust-versions). + - **PostgreSQL execution lifecycle ownership**: Proxy now tracks prepared statements, portals, Describe operations, execution outcomes, and execution metrics as one connection-local protocol lifecycle. Suspended executions retain their original metrics scope until completion, repeated portal executions receive distinct scopes, and terminal errors replace upstream responses atomically while schema outcomes are reported exactly once. - **Upstream TLS verification for client traffic**: Connections with `with_tls_verification` enabled now use a cached snapshot of the system root certificates, loaded once when Proxy starts. Unlike Proxy's background database connections, pg-proto client-traffic connections do not apply operating-system revocation checks or enterprise verification policy. Restart Proxy after changing the system trust store. diff --git a/Cargo.toml b/Cargo.toml index 52c9de7b0..91d8d148c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,10 @@ members = ["packages/*"] [workspace.package] version = "3.0.1" edition = "2021" +# Minimum supported Rust version (MSRV). CI builds the production binary on +# exactly this toolchain. See "Supported Rust versions" in DEVELOPMENT.md +# before changing it. +rust-version = "1.89.0" [profile.dev] incremental = true diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 6732f92be..a3ee6f99e 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -137,6 +137,43 @@ Install development and testing dependencies (including `cargo-binstall`): mise install ``` +### Supported Rust versions + +CI uses three Rust toolchains: + +| Toolchain | Declared in | What CI runs on it | +|---|---|---| +| **Pinned** (currently 1.99.0) | `rust-toolchain.toml` | Formatting, Clippy, unit and integration tests across the full PostgreSQL matrix, burn-in, benchmarks, and release binaries (`mise run build:binary`). | +| **Latest stable** | floating `stable` channel | `Quick check (Rust stable)`: formatting and Clippy only. | +| **Minimum supported (MSRV)** (currently 1.89.0) | `rust-version` under `[workspace.package]` in `Cargo.toml` | `Quick check (Rust MSRV)`: builds the production binary with `cargo build --locked --release --package cipherstash-proxy`. | + +The quick checks need no PostgreSQL or credentials. Locally, rustup selects the pinned toolchain automatically from `rust-toolchain.toml`. + +Rust 1.88 cannot build Proxy: a transitive dependency (`stack-profile`, via `cipherstash-client`) uses `std::fs::File::lock`, which stabilized in 1.89, without declaring that requirement. + +To run the quick checks locally: + +```shell +cargo +stable clippy --all --no-deps --all-targets --all-features -- -D warnings + +rustup toolchain install 1.89.0 --profile minimal +cargo +1.89.0 build --locked --release --package cipherstash-proxy +``` + +#### Bumping the pinned toolchain + +When `Quick check (Rust stable)` fails after a new Rust release, fix the new warnings and update `channel` in `rust-toolchain.toml` to that release in the same pull request. The full matrix then confirms the new pin. + +#### Raising the MSRV + +The MSRV only goes up deliberately. If `Quick check (Rust MSRV)` fails because a change, or a dependency update in `Cargo.lock`, needs a newer compiler, either avoid the newer requirement (for example, keep the older dependency version) or raise the MSRV in the same pull request: + +1. Update `rust-version` in the root `Cargo.toml`. CI picks up the new value automatically. +2. Update the current MSRV and the reason for it in this section. +3. Add a `### Changed` entry to the `[Unreleased]` section of `CHANGELOG.md` naming the new minimum and why it changed, because it affects anyone building Proxy from source. + +Lowering the MSRV requires confirming that `Quick check (Rust MSRV)` passes on the lower version first. + ### PostgreSQL > [!IMPORTANT] diff --git a/packages/cipherstash-proxy-burn-in/Cargo.toml b/packages/cipherstash-proxy-burn-in/Cargo.toml index efceac113..0c0dee4c6 100644 --- a/packages/cipherstash-proxy-burn-in/Cargo.toml +++ b/packages/cipherstash-proxy-burn-in/Cargo.toml @@ -2,6 +2,7 @@ name = "cipherstash-proxy-burn-in" version = "0.1.0" edition.workspace = true +rust-version.workspace = true publish = false [dependencies] diff --git a/packages/cipherstash-proxy-integration/Cargo.toml b/packages/cipherstash-proxy-integration/Cargo.toml index 82fe7bf6f..803e623a5 100644 --- a/packages/cipherstash-proxy-integration/Cargo.toml +++ b/packages/cipherstash-proxy-integration/Cargo.toml @@ -2,6 +2,7 @@ name = "cipherstash-proxy-integration" version = "0.1.0" edition = "2021" +rust-version.workspace = true [dependencies] bytes = "1.10.1" diff --git a/packages/cipherstash-proxy/Cargo.toml b/packages/cipherstash-proxy/Cargo.toml index 99cbcfe4c..4320170d6 100644 --- a/packages/cipherstash-proxy/Cargo.toml +++ b/packages/cipherstash-proxy/Cargo.toml @@ -2,6 +2,7 @@ name = "cipherstash-proxy" version.workspace = true edition = "2021" +rust-version.workspace = true [dependencies] async-trait = "0.1" diff --git a/packages/eql-mapper-macros/Cargo.toml b/packages/eql-mapper-macros/Cargo.toml index 1cb0dc120..36ca35b4c 100644 --- a/packages/eql-mapper-macros/Cargo.toml +++ b/packages/eql-mapper-macros/Cargo.toml @@ -3,6 +3,7 @@ name = "eql-mapper-macros" description = "Macros to reduce boilerplate in the implementation of eql-mapper" version.workspace = true edition.workspace = true +rust-version.workspace = true publish = false [lib] diff --git a/packages/eql-mapper/Cargo.toml b/packages/eql-mapper/Cargo.toml index bd26bc565..dd4e01e8f 100644 --- a/packages/eql-mapper/Cargo.toml +++ b/packages/eql-mapper/Cargo.toml @@ -3,6 +3,7 @@ name = "eql-mapper" description = "The SQL transformation layer of CipherStash Proxy. Safely transforms SQL to SQL+EQL using a reference schema and type inference approach" version = "1.0.0" edition = "2021" +rust-version.workspace = true authors = [ "James Sadler ", "Yuji Yokoo ", diff --git a/packages/showcase/Cargo.toml b/packages/showcase/Cargo.toml index d8a7f1245..59ebf1b5a 100644 --- a/packages/showcase/Cargo.toml +++ b/packages/showcase/Cargo.toml @@ -2,6 +2,7 @@ name = "showcase" version.workspace = true edition.workspace = true +rust-version.workspace = true description = "Healthcare data model demonstrating EQL v3 searchable encryption with realistic encrypted application patterns" [dependencies] From b97a4ff7646fc0856e3b06e3394e9b8aa9ed7041 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 15 Oct 2026 01:02:21 +0000 Subject: [PATCH 2/2] ci: rename toolchain checks to Build (Rust MSRV) and Lint (Rust stable) Avoids confusion with QuickCheck-style property testing. Claude-Session: https://claude.ai/code/session_01PeBRsmwf2siZczh49FAPfe --- .github/workflows/test.yml | 6 +++--- DEVELOPMENT.md | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 464c81e52..b8d591681 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -67,13 +67,13 @@ jobs: channel: engineering webhook_url: ${{ secrets.SLACK_NOTIFICATION_WEBHOOK_URL }} - # Quick checks outside the pinned toolchain. Neither needs PostgreSQL, + # Toolchain checks outside the pinned toolchain. Neither needs PostgreSQL, # credentials, or the test matrix. # # MSRV: builds the production binary on `rust-version` from Cargo.toml, so a # change that raises the compiler requirement fails here. msrv: - name: Quick check (Rust MSRV) + name: Build (Rust MSRV) runs-on: blacksmith-16vcpu-ubuntu-2204 timeout-minutes: 30 @@ -123,7 +123,7 @@ jobs: # Latest stable: early warning that a new Rust release breaks the build or # adds Clippy lints, before the pinned toolchain is bumped to it. stable: - name: Quick check (Rust stable) + name: Lint (Rust stable) runs-on: blacksmith-16vcpu-ubuntu-2204 timeout-minutes: 30 env: diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index a3ee6f99e..a8a0f457f 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -144,14 +144,14 @@ CI uses three Rust toolchains: | Toolchain | Declared in | What CI runs on it | |---|---|---| | **Pinned** (currently 1.99.0) | `rust-toolchain.toml` | Formatting, Clippy, unit and integration tests across the full PostgreSQL matrix, burn-in, benchmarks, and release binaries (`mise run build:binary`). | -| **Latest stable** | floating `stable` channel | `Quick check (Rust stable)`: formatting and Clippy only. | -| **Minimum supported (MSRV)** (currently 1.89.0) | `rust-version` under `[workspace.package]` in `Cargo.toml` | `Quick check (Rust MSRV)`: builds the production binary with `cargo build --locked --release --package cipherstash-proxy`. | +| **Latest stable** | floating `stable` channel | `Lint (Rust stable)`: formatting and Clippy only. | +| **Minimum supported (MSRV)** (currently 1.89.0) | `rust-version` under `[workspace.package]` in `Cargo.toml` | `Build (Rust MSRV)`: builds the production binary with `cargo build --locked --release --package cipherstash-proxy`. | -The quick checks need no PostgreSQL or credentials. Locally, rustup selects the pinned toolchain automatically from `rust-toolchain.toml`. +The MSRV build and stable lint jobs need no PostgreSQL or credentials. Locally, rustup selects the pinned toolchain automatically from `rust-toolchain.toml`. Rust 1.88 cannot build Proxy: a transitive dependency (`stack-profile`, via `cipherstash-client`) uses `std::fs::File::lock`, which stabilized in 1.89, without declaring that requirement. -To run the quick checks locally: +To run those checks locally: ```shell cargo +stable clippy --all --no-deps --all-targets --all-features -- -D warnings @@ -162,17 +162,17 @@ cargo +1.89.0 build --locked --release --package cipherstash-proxy #### Bumping the pinned toolchain -When `Quick check (Rust stable)` fails after a new Rust release, fix the new warnings and update `channel` in `rust-toolchain.toml` to that release in the same pull request. The full matrix then confirms the new pin. +When `Lint (Rust stable)` fails after a new Rust release, fix the new warnings and update `channel` in `rust-toolchain.toml` to that release in the same pull request. The full matrix then confirms the new pin. #### Raising the MSRV -The MSRV only goes up deliberately. If `Quick check (Rust MSRV)` fails because a change, or a dependency update in `Cargo.lock`, needs a newer compiler, either avoid the newer requirement (for example, keep the older dependency version) or raise the MSRV in the same pull request: +The MSRV only goes up deliberately. If `Build (Rust MSRV)` fails because a change, or a dependency update in `Cargo.lock`, needs a newer compiler, either avoid the newer requirement (for example, keep the older dependency version) or raise the MSRV in the same pull request: 1. Update `rust-version` in the root `Cargo.toml`. CI picks up the new value automatically. 2. Update the current MSRV and the reason for it in this section. 3. Add a `### Changed` entry to the `[Unreleased]` section of `CHANGELOG.md` naming the new minimum and why it changed, because it affects anyone building Proxy from source. -Lowering the MSRV requires confirming that `Quick check (Rust MSRV)` passes on the lower version first. +Lowering the MSRV requires confirming that `Build (Rust MSRV)` passes on the lower version first. ### PostgreSQL