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
14 changes: 7 additions & 7 deletions .github/workflows/maintenance-queue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,11 @@ jobs:
<!-- ${marker} -->
<!-- automation-queue:dependency -->

`cargo upgrade` reports a newer manifest dependency requirement for **${dep}**.
\`cargo upgrade\` reports a newer manifest dependency requirement for **${dep}**.

${details}

Update this dependency everywhere appropriate, including incompatible/major changes. Read the crate's changelog/release notes where useful, adapt code to current APIs and best practices, refresh `Cargo.lock`, and run the full relevant CI/test suite. Do not skip an update merely because it is transitive, low-risk, or already SemVer-compatible.
Update this dependency everywhere appropriate, including incompatible/major changes. Read the crate's changelog/release notes where useful, adapt code to current APIs and best practices, refresh \`Cargo.lock\`, and run the full relevant CI/test suite. Do not skip an update merely because it is transitive, low-risk, or already SemVer-compatible.

This issue is generated and refreshed automatically. A ChatGPT maintenance automation is expected to implement it.
EOF
Expand Down Expand Up @@ -179,7 +179,7 @@ jobs:
log="$(tail -n 200 /tmp/cargo-upgrade.log)"
body="$(cat <<EOF
<!-- ${marker} -->
The passive dependency detector failed while running `cargo upgrade`.
The passive dependency detector failed while running \`cargo upgrade\`.

\`\`\`text
${log}
Expand Down Expand Up @@ -233,7 +233,7 @@ jobs:
<!-- ${marker} -->
<!-- automation-queue:lockfile -->

A plain `cargo update` changes `Cargo.lock`, so there are compatible and/or transitive dependency updates available even if no manifest requirement needs changing.
A plain \`cargo update\` changes \`Cargo.lock\`, so there are compatible and/or transitive dependency updates available even if no manifest requirement needs changing.

\`\`\`text
${stat}
Expand All @@ -252,7 +252,7 @@ jobs:
gh issue create --repo "$REPO" --title "deps: refresh Cargo.lock" --label "automation:lockfile" --body "$body"
fi
elif [[ -n "$existing" ]]; then
gh issue close "$existing" --repo "$REPO" --reason completed --comment "Closed automatically: `cargo update` no longer changes Cargo.lock."
gh issue close "$existing" --repo "$REPO" --reason completed --comment "Closed automatically: \`cargo update\` no longer changes Cargo.lock."
fi

- name: Report cargo-update detector failure
Expand All @@ -268,7 +268,7 @@ jobs:
log="$(tail -n 200 /tmp/cargo-update.log)"
body="$(cat <<EOF
<!-- ${marker} -->
The passive dependency detector failed while running `cargo update`.
The passive dependency detector failed while running \`cargo update\`.

\`\`\`text
${log}
Expand Down Expand Up @@ -321,7 +321,7 @@ jobs:

- Read the official Rust ${VERSION} announcement and detailed release notes/changelog.
- Review relevant language, standard-library, rustc, Cargo, Clippy, rustfmt, target/platform, and tooling changes.
- Review all Rust code, `Cargo.toml`/`Cargo.lock`, CI, Docker/build tooling, `SKILL.md`, README/docs, examples, lints, and project conventions for newly preferable patterns or obsolete workarounds.
- Review all Rust code, \`Cargo.toml\`/\`Cargo.lock\`, CI, Docker/build tooling, \`SKILL.md\`, README/docs, examples, lints, and project conventions for newly preferable patterns or obsolete workarounds.
- Adopt useful newly-stable features and current best practices where they improve the project; remove workarounds that the new stable release makes unnecessary.
- Update the current-stable CI/toolchain references while preserving the intentional MSRV contract unless there is a separately justified reason to raise it.
- Run the full CI-equivalent test matrix and fix fallout.
Expand Down
57 changes: 17 additions & 40 deletions Cargo.lock

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

6 changes: 2 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ uuid = { version = "1.26", features = ["serde"] }
wasm-bindgen = "0.2"
axum-prometheus = "0.10"
tower_governor = { version = "0.8", features = ["axum"] }
axum-valid = "0.25"
validator = { version = "0.20", features = ["derive"] }
validator = { version = "0.21", features = ["derive"] }
aws-lc-rs = "1"
moka = { version = "0.12", features = ["future"] }
stylance = "0.8"
Expand All @@ -68,8 +67,7 @@ console-subscriber = "0.5"
criterion = { version = "0.8", features = ["html_reports"] }
insta = "1"
proptest = "1"
testcontainers = "0.27"
testcontainers-modules = { version = "0.15", features = ["postgres"] }
testcontainers = "0.28"
# Layered config: TOML file + RWF_* environment variable overrides.
# The `config` crate gives us typed deserialization + per-source priority
# without needing unsafe or hand-rolled merge logic.
Expand Down
1 change: 0 additions & 1 deletion e2e-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ opentelemetry_sdk = { workspace = true, optional = true, features = ["testing"]

# Test infrastructure
testcontainers = { workspace = true }
testcontainers-modules = { workspace = true }

# Snapshot testing & property-based testing
insta = { workspace = true, features = ["json"] }
Expand Down
20 changes: 15 additions & 5 deletions e2e-tests/src/common/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@

use anyhow::{Context, Result};
use sqlx::PgPool;
use testcontainers::core::{IntoContainerPort, WaitFor};
use testcontainers::runners::AsyncRunner;
use testcontainers::{ContainerAsync, ImageExt};
use testcontainers_modules::postgres::Postgres;
use testcontainers::{ContainerAsync, GenericImage, ImageExt};

/// RAII guard for a test-scoped Postgres database.
pub struct TestEnv {
pool: PgPool,
connection_string: String,
#[allow(dead_code, reason = "Kept alive for Drop side-effect on TestEnv")]
container: Box<ContainerAsync<Postgres>>,
container: Box<ContainerAsync<GenericImage>>,
}

impl std::fmt::Debug for TestEnv {
Expand All @@ -40,8 +40,18 @@ impl TestEnv {
/// Returns an error if the container cannot start, its host/port cannot be
/// resolved, the pool cannot connect, migrations fail, or seeding fails.
pub async fn postgres() -> Result<Self> {
let container = Postgres::default()
.with_tag("17-alpine")
let container = GenericImage::new("postgres", "17-alpine")
.with_exposed_port(5432.tcp())
.with_wait_for(WaitFor::message_on_stderr(
"database system is ready to accept connections",
))
.with_wait_for(WaitFor::message_on_stdout(
"database system is ready to accept connections",
))
.with_env_var("POSTGRES_DB", "postgres")
.with_env_var("POSTGRES_USER", "postgres")
.with_env_var("POSTGRES_PASSWORD", "postgres")
.with_cmd(["-c", "fsync=off"])
.start()
.await
.context("Failed to start Postgres testcontainer")?;
Expand Down
1 change: 0 additions & 1 deletion gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ dev-tools = ["dep:console-subscriber"]
anyhow = { workspace = true }
axum = { workspace = true }
axum-prometheus = { workspace = true }
axum-valid = { workspace = true }
chrono = { workspace = true }
aws-lc-rs = { workspace = true }
base64 = { workspace = true }
Expand Down
18 changes: 11 additions & 7 deletions gateway/src/auth/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! * Rate limiting is applied at the router level via `tower_governor`.
//! * JWT errors are mapped to distinct error variants.
//! * Secrets (passwords, tokens) are never included in log output.
//! * Public auth request payloads are typed and validated with `axum-valid`.
//! * Public auth request payloads are typed and validated with `validator`.

use std::str::FromStr;

Expand Down Expand Up @@ -88,10 +88,12 @@ pub struct ProtectedResponse {
pub async fn login_handler(
State(state): State<GatewayState>,
session: tower_sessions::Session,
axum_valid::Valid(axum::Json(LoginRequest { user_id, password })): axum_valid::Valid<
axum::Json<LoginRequest>,
>,
axum::Json(request): axum::Json<LoginRequest>,
) -> Result<Json<LoginResponse>, AppError> {
request
.validate()
.map_err(|_| AppError::BadRequest("invalid request payload".to_string()))?;
let LoginRequest { user_id, password } = request;
let s = &state.settings;
let parsed_user_id = UserId::from_str(&user_id)?;

Expand Down Expand Up @@ -219,10 +221,12 @@ async fn remove_unissued_refresh_token(pool: &sqlx::PgPool, refresh_jti: Uuid) {
/// access, or JWT creation fails.
pub async fn refresh_handler(
State(state): State<GatewayState>,
axum_valid::Valid(axum::Json(RefreshRequest { refresh_token })): axum_valid::Valid<
axum::Json<RefreshRequest>,
>,
axum::Json(request): axum::Json<RefreshRequest>,
) -> Result<Json<RefreshResponse>, AppError> {
request
.validate()
.map_err(|_| AppError::BadRequest("invalid request payload".to_string()))?;
let RefreshRequest { refresh_token } = request;
let pool = state.db_pool.as_ref().ok_or_else(|| {
AppError::internal(
"refresh-token store unavailable",
Expand Down
Loading