From 2a4541c7441fa42fb94b1c644940b85a6a150ca1 Mon Sep 17 00:00:00 2001 From: Matthew Grossman Date: Fri, 23 Oct 2026 15:08:41 -0700 Subject: [PATCH 1/5] feat(testkit): pass extra environment variables to the CLI Add Cli::run_with_env and Context::cli_with_env so tests can hand credentials to the CLI by name instead of on its command line. Signed-off-by: Matthew Grossman --- tests/testkit/testkit/src/cli.rs | 17 +++++++++++++++++ tests/testkit/testkit/src/context.rs | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/tests/testkit/testkit/src/cli.rs b/tests/testkit/testkit/src/cli.rs index 7bedd9a3f2..de29a51148 100644 --- a/tests/testkit/testkit/src/cli.rs +++ b/tests/testkit/testkit/src/cli.rs @@ -77,6 +77,22 @@ impl Cli { /// Like [`Cli::run`], with `dir` as the working directory. pub async fn run_in(&self, dir: Option<&Path>, args: I) -> Result + where + I: IntoIterator, + S: AsRef, + { + self.run_with_env(dir, &[], args).await + } + + /// Like [`Cli::run_in`], with extra environment variables for the CLI, + /// such as a credential it reads by name. Values are not included in + /// [`CliOutput::command`] or in errors, so they can hold secrets. + pub async fn run_with_env( + &self, + dir: Option<&Path>, + env: &[(&str, &str)], + args: I, + ) -> Result where I: IntoIterator, S: AsRef, @@ -111,6 +127,7 @@ impl Cli { if let Some(dir) = dir { process.current_dir(dir); } + process.envs(env.iter().copied()); let output = tokio::time::timeout(CLI_TIMEOUT, process.output()) .await diff --git a/tests/testkit/testkit/src/context.rs b/tests/testkit/testkit/src/context.rs index 24e3f0a37a..a753496a78 100644 --- a/tests/testkit/testkit/src/context.rs +++ b/tests/testkit/testkit/src/context.rs @@ -72,6 +72,17 @@ impl Context { self.cli.run_in(Some(dir), args).await } + /// Like [`Context::cli`], with extra environment variables for the CLI. + /// Pass secrets this way rather than as arguments: values are not + /// included in the reported command or in errors. + pub async fn cli_with_env(&self, env: &[(&str, &str)], args: I) -> Result + where + I: IntoIterator, + S: AsRef, + { + self.cli.run_with_env(None, env, args).await + } + /// The ID unique to this test run, used in resource names. pub fn run_id(&self) -> &str { &self.run_id From a345296826daca19477a5903d5cc0266321811c6 Mon Sep 17 00:00:00 2001 From: Matthew Grossman Date: Fri, 23 Oct 2026 15:45:33 -0700 Subject: [PATCH 2/5] feat(tmachine): add an Ubuntu Docker environment that runs Keycloak Environment setup can now take inputs, like installers do, and hashes them only when present so existing cached disks stay valid. ubuntu-docker-rootful-keycloak runs the Docker setup plus a Keycloak playbook that starts the container with a restart policy, since setup is cached as a disk, and writes how to reach it as OPENSHELL_TEST_* lines in /etc/openshell-test/env.d/keycloak.env. Signed-off-by: Matthew Grossman --- .../tmachine/ansible/playbooks/keycloak.yaml | 39 +++++++++++++++++++ .../ansible/roles/keycloak/tasks/main.yaml | 4 ++ tests/tmachine/config.nix | 15 +++++++ tests/tmachine/src/config.rs | 3 ++ tests/tmachine/src/qemu/setup.rs | 9 +++-- 5 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 tests/tmachine/ansible/playbooks/keycloak.yaml diff --git a/tests/tmachine/ansible/playbooks/keycloak.yaml b/tests/tmachine/ansible/playbooks/keycloak.yaml new file mode 100644 index 0000000000..dcf1b8c273 --- /dev/null +++ b/tests/tmachine/ansible/playbooks/keycloak.yaml @@ -0,0 +1,39 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# Run Keycloak in the environment and publish how tests reach it. +# +# Environment setup applies this once and caches the disk, so the container +# restarts on every boot (see the keycloak role). Tests read the variables in +# the env file below through openshell-test-runner, which passes every +# /etc/openshell-test/env.d/*.env file to them. The keycloak features suite +# (tests/suites/features/keycloak) reads them. +--- +- name: Keycloak for tests + hosts: all + gather_facts: false + roles: + - keycloak + tasks: + - name: Create the test environment directory + become: true + ansible.builtin.file: + path: /etc/openshell-test/env.d + state: directory + owner: root + group: root + mode: "0755" + + # The values are the throwaway fixture realm's (scripts/keycloak-realm.json). + - name: Publish Keycloak test variables + become: true + ansible.builtin.copy: + dest: /etc/openshell-test/env.d/keycloak.env + owner: tmachine + group: tmachine + mode: "0600" + content: | + OPENSHELL_TEST_KEYCLOAK_ISSUER=http://127.0.0.1:{{ keycloak_port }}/realms/{{ keycloak_realm }} + OPENSHELL_TEST_KEYCLOAK_CLIENT_ID=openshell-cli + OPENSHELL_TEST_KEYCLOAK_USERNAME=admin@test + OPENSHELL_TEST_KEYCLOAK_PASSWORD=admin diff --git a/tests/tmachine/ansible/roles/keycloak/tasks/main.yaml b/tests/tmachine/ansible/roles/keycloak/tasks/main.yaml index ca0743ad26..4ba39533b4 100644 --- a/tests/tmachine/ansible/roles/keycloak/tasks/main.yaml +++ b/tests/tmachine/ansible/roles/keycloak/tasks/main.yaml @@ -72,6 +72,10 @@ - --detach - --name - "{{ keycloak_container_name }}" + # Environment setup bakes the container into a cached disk; it must + # come back when a session boots from that disk. + - --restart + - unless-stopped - --publish - "127.0.0.1:{{ keycloak_port }}:8080" - --env diff --git a/tests/tmachine/config.nix b/tests/tmachine/config.nix index 843b1d52e1..37c36d3628 100644 --- a/tests/tmachine/config.nix +++ b/tests/tmachine/config.nix @@ -52,6 +52,21 @@ let ]; }; } + { + name = "ubuntu-docker-rootful-keycloak"; + machine = "ubuntu"; + setup = { + use_galaxy = true; + playbooks = [ + "ansible/playbooks/nextest.yaml" + "ansible/playbooks/docker.yaml" + "ansible/playbooks/keycloak.yaml" + ]; + inputs = { + keycloak_realm_file = "../../scripts/keycloak-realm.json"; + }; + }; + } { name = "ubuntu-k3s"; machine = "ubuntu"; diff --git a/tests/tmachine/src/config.rs b/tests/tmachine/src/config.rs index bc19cbbb1f..84f67e90ec 100644 --- a/tests/tmachine/src/config.rs +++ b/tests/tmachine/src/config.rs @@ -32,6 +32,9 @@ pub struct Environment { pub struct Setup { pub use_galaxy: bool, pub playbooks: Vec, + /// Files the setup playbooks read, such as a service's fixture data. + #[serde(default)] + pub inputs: BTreeMap, } #[derive(Clone, Deserialize)] diff --git a/tests/tmachine/src/qemu/setup.rs b/tests/tmachine/src/qemu/setup.rs index 993e7932b3..185d6c290b 100644 --- a/tests/tmachine/src/qemu/setup.rs +++ b/tests/tmachine/src/qemu/setup.rs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -use std::collections::BTreeMap; use std::path::PathBuf; use anyhow::{Context, Result}; @@ -10,7 +9,7 @@ use blake3::Hasher; use crate::config::{Environment, Machine}; use super::ansible_hash::hash_sources; -use super::layer::{cached_layer, hash_file, hash_files}; +use super::layer::{cached_layer, hash_file, hash_files, hash_inputs}; const SETUP_CACHE_VERSION: &[u8] = b"tmachine-disk-blake3-v1"; @@ -25,7 +24,7 @@ pub async fn setup(machine: &Machine, environment: &Environment) -> Result Result { hash_sources(&mut hasher).context("failed to hash Ansible sources")?; hash_files(&mut hasher, &environment.setup.playbooks) .context("failed to hash setup playbooks")?; + // Skipped when empty so environments without inputs keep their cache keys. + if !environment.setup.inputs.is_empty() { + hash_inputs(&mut hasher, &environment.setup.inputs)?; + } Ok(hasher.finalize().to_hex().to_string()) } From 33501a3f5dc48de307e60c511cc08e8174d9b185 Mon Sep 17 00:00:00 2001 From: Matthew Grossman Date: Fri, 23 Oct 2026 15:46:09 -0700 Subject: [PATCH 3/5] feat(test-runner): pass the variables an environment publishes to tests After boot, read every /etc/openshell-test/env.d/*.env file, accept only OPENSHELL_TEST_* names, and add the variables to the testkit-ready and nextest commands through guest_env. Errors name the key, never the value. The runner doesn't know which services an environment runs; suites read the variables, so they also run against a deployment that sets them. Signed-off-by: Matthew Grossman --- tests/runner/src/execute.rs | 31 +++++++-- tests/runner/src/lib.rs | 1 + tests/runner/src/test_env.rs | 123 +++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 tests/runner/src/test_env.rs diff --git a/tests/runner/src/execute.rs b/tests/runner/src/execute.rs index a4d75d19b2..aa9c0992bf 100644 --- a/tests/runner/src/execute.rs +++ b/tests/runner/src/execute.rs @@ -7,7 +7,9 @@ //! //! Tests find the gateway the way the CLI does, so the runner points them at //! the one the installer registered with `OPENSHELL_GATEWAY` and at the -//! installed CLI with `OPENSHELL_BIN`. +//! installed CLI with `OPENSHELL_BIN`. Anything else the environment provides, +//! such as Keycloak, the tests learn from the variables it publishes (see +//! [`crate::test_env`]). //! //! Adapted from the executor in Evan Lezar's NVIDIA/OpenShell#4629. @@ -21,6 +23,7 @@ use tmachine::config::Config; use crate::bundle::{Bundle, PROFILE, READY_BINARY}; use crate::report::{Status, decide_status}; +use crate::test_env; const GUEST_DIR: &str = "/var/tmp/openshell-tests"; /// How long the gateway has to become healthy after the environment is up. @@ -126,13 +129,15 @@ async fn provision(config: &Config, environment: &str, installer: &str) -> Resul } /// The environment variables that point the tests at the system under test: -/// the registered gateway, if known, and the installed CLI. -pub fn guest_env(gateway: Option<&str>, openshell_bin: &str) -> Vec { +/// the registered gateway, if known, the installed CLI, and what the +/// environment publishes for tests (see [`test_env`]). +pub fn guest_env(gateway: Option<&str>, openshell_bin: &str, test_env: &[String]) -> Vec { let mut vars = Vec::new(); if let Some(gateway) = gateway { vars.push(format!("OPENSHELL_GATEWAY={gateway}")); } vars.push(format!("OPENSHELL_BIN={openshell_bin}")); + vars.extend(test_env.iter().cloned()); vars } @@ -166,7 +171,10 @@ async fn run_tests(session: &Session, run: &Run<'_>) -> Result { !openshell_bin.is_empty(), "the installer did not put openshell on the guest's PATH" ); - let env = guest_env(run.gateway, openshell_bin); + let test_env = test_env::read(session) + .await + .context("read the variables the environment publishes for tests")?; + let env = guest_env(run.gateway, openshell_bin, &test_env); let guest = GUEST_DIR; checked( @@ -279,15 +287,26 @@ mod tests { #[test] fn points_tests_at_the_gateway_and_the_cli() { assert_eq!( - guest_env(Some("openshell"), "/usr/bin/openshell"), + guest_env(Some("openshell"), "/usr/bin/openshell", &[]), [ "OPENSHELL_GATEWAY=openshell", "OPENSHELL_BIN=/usr/bin/openshell", ] ); assert_eq!( - guest_env(None, "/usr/bin/openshell"), + guest_env(None, "/usr/bin/openshell", &[]), ["OPENSHELL_BIN=/usr/bin/openshell"] ); + assert_eq!( + guest_env( + None, + "/usr/bin/openshell", + &["OPENSHELL_TEST_KEYCLOAK_ISSUER=http://127.0.0.1:8180/realms/openshell".into()] + ), + [ + "OPENSHELL_BIN=/usr/bin/openshell", + "OPENSHELL_TEST_KEYCLOAK_ISSUER=http://127.0.0.1:8180/realms/openshell", + ] + ); } } diff --git a/tests/runner/src/lib.rs b/tests/runner/src/lib.rs index 1d8821362d..8402c06a25 100644 --- a/tests/runner/src/lib.rs +++ b/tests/runner/src/lib.rs @@ -8,3 +8,4 @@ pub mod bundle; pub mod execute; pub mod report; +pub mod test_env; diff --git a/tests/runner/src/test_env.rs b/tests/runner/src/test_env.rs new file mode 100644 index 0000000000..cc616da3fc --- /dev/null +++ b/tests/runner/src/test_env.rs @@ -0,0 +1,123 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Variables an environment publishes for its tests. +//! +//! An environment that runs something besides `OpenShell`, such as Keycloak, +//! says how tests reach it in `/etc/openshell-test/env.d/*.env`: one +//! `OPENSHELL_TEST_*=value` per line. The tmachine environment's setup +//! writes the file; the runner passes its variables to the tests, and suite +//! fixtures read them. Tests don't depend on tmachine: anyone running a suite +//! against their own deployment sets the same variables. + +use anyhow::{Context, Result, bail, ensure}; +use tmachine::Session; + +/// Where environments publish the variables tests read. +pub const ENV_DIR: &str = "/etc/openshell-test/env.d"; +/// The prefix every published variable must have, so an environment can't +/// override how tests find the gateway or the CLI. +pub const ENV_PREFIX: &str = "OPENSHELL_TEST_"; + +/// Read the variables the booted environment publishes, as `KEY=VALUE` +/// strings. An environment that publishes none has no `ENV_DIR`. +pub async fn read(session: &Session) -> Result> { + let script = format!( + "for f in {ENV_DIR}/*.env; do [ -e \"$f\" ] || continue; printf '\\0%s\\n' \"$f\"; cat \"$f\"; done" + ); + let output = session.exec(&["sh", "-c", &script]).await?; + ensure!( + output.status.success(), + "read {ENV_DIR}: {}", + String::from_utf8_lossy(&output.stderr).trim() + ); + let contents = + String::from_utf8(output.stdout).with_context(|| format!("{ENV_DIR} is not UTF-8"))?; + parse_files(&contents) +} + +/// Parse the files `read` prints: each is a NUL, its path and a newline, +/// then its contents. +fn parse_files(output: &str) -> Result> { + let mut vars = Vec::new(); + for file in output.split('\0').filter(|file| !file.is_empty()) { + let (path, body) = file.split_once('\n').unwrap_or((file, "")); + vars.extend(parse_env(path, body)?); + } + Ok(vars) +} + +/// Parse a published env file: `KEY=VALUE` lines, blank lines and `#` +/// comments. Values are taken literally; there is no quoting. Errors name +/// the key, never the value, since values can be credentials. +pub fn parse_env(path: &str, contents: &str) -> Result> { + let mut vars = Vec::new(); + for (number, line) in contents.lines().enumerate() { + let line = line.trim_end(); + if line.trim().is_empty() || line.trim_start().starts_with('#') { + continue; + } + let Some((key, _value)) = line.split_once('=') else { + bail!("{path}:{}: expected KEY=VALUE", number + 1); + }; + ensure!( + key.starts_with(ENV_PREFIX) + && key.len() > ENV_PREFIX.len() + && key + .bytes() + .all(|b| b.is_ascii_uppercase() || b.is_ascii_digit() || b == b'_'), + "{path}:{}: {key:?} is not an {ENV_PREFIX}* variable name", + number + 1 + ); + vars.push(line.to_string()); + } + Ok(vars) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parses_published_variables() { + let vars = parse_env( + "keycloak.env", + "# Published by keycloak.yaml\n\nOPENSHELL_TEST_KEYCLOAK_ISSUER=http://127.0.0.1:8180/realms/openshell\nOPENSHELL_TEST_KEYCLOAK_PASSWORD=a=b\n", + ) + .unwrap(); + assert_eq!( + vars, + [ + "OPENSHELL_TEST_KEYCLOAK_ISSUER=http://127.0.0.1:8180/realms/openshell", + "OPENSHELL_TEST_KEYCLOAK_PASSWORD=a=b", + ] + ); + } + + #[test] + fn reads_every_published_file() { + assert_eq!(parse_files("").unwrap(), Vec::::new()); + let vars = parse_files( + "\0/etc/openshell-test/env.d/a.env\nOPENSHELL_TEST_A=1\n\0/etc/openshell-test/env.d/b.env\nOPENSHELL_TEST_B=2", + ) + .unwrap(); + assert_eq!(vars, ["OPENSHELL_TEST_A=1", "OPENSHELL_TEST_B=2"]); + + let err = parse_files("\0/etc/openshell-test/env.d/b.env\nPATH=/x\n").unwrap_err(); + assert!(err.to_string().contains("b.env:1"), "{err}"); + } + + #[test] + fn refuses_variables_outside_the_prefix() { + let err = parse_env("x.env", "OPENSHELL_GATEWAY=other\n").unwrap_err(); + assert!(err.to_string().contains("OPENSHELL_GATEWAY"), "{err}"); + } + + #[test] + fn errors_do_not_echo_values() { + let err = parse_env("x.env", "openshell_test_secret=hunter2\n").unwrap_err(); + assert!(!err.to_string().contains("hunter2"), "{err}"); + let err = parse_env("x.env", "hunter2\n").unwrap_err(); + assert!(!err.to_string().contains("hunter2"), "{err}"); + } +} From 7adbd3d678a34c323b504627e1a77fc34b935132 Mon Sep 17 00:00:00 2001 From: Matthew Grossman Date: Fri, 23 Oct 2026 15:48:03 -0700 Subject: [PATCH 4/5] test(features): port Keycloak provider refresh to testkit Add a keycloak features crate with a suite-local KeycloakContext fixture that reads OPENSHELL_TEST_KEYCLOAK_*, waits for the realm to answer, and provides password grants, revocation and the token endpoint. Port the provider refresh test onto it. Align the features lockfile with the root and add it to the alignment check. The old provider-refresh crate stays until the required lanes switch. Signed-off-by: Matthew Grossman --- .../scripts/check_cargo_lockfile_alignment.py | 1 + tests/suites/features/Cargo.lock | 1605 +++++++++++++---- tests/suites/features/Cargo.toml | 2 +- tests/suites/features/keycloak/Cargo.toml | 18 + tests/suites/features/keycloak/src/lib.rs | 278 +++ .../keycloak/tests/provider_refresh.rs | 178 ++ 6 files changed, 1759 insertions(+), 323 deletions(-) create mode 100644 tests/suites/features/keycloak/Cargo.toml create mode 100644 tests/suites/features/keycloak/src/lib.rs create mode 100644 tests/suites/features/keycloak/tests/provider_refresh.rs diff --git a/tasks/scripts/check_cargo_lockfile_alignment.py b/tasks/scripts/check_cargo_lockfile_alignment.py index 29e82588af..987fef0f6d 100644 --- a/tasks/scripts/check_cargo_lockfile_alignment.py +++ b/tasks/scripts/check_cargo_lockfile_alignment.py @@ -38,6 +38,7 @@ ALIGNED_WORKSPACES = ( "tests/testkit", "tests/suites/conformance", + "tests/suites/features", ) diff --git a/tests/suites/features/Cargo.lock b/tests/suites/features/Cargo.lock index 24b386a25c..29d26c69f8 100644 --- a/tests/suites/features/Cargo.lock +++ b/tests/suites/features/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + [[package]] name = "ahash" version = "0.8.12" @@ -17,9 +32,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.5" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -30,11 +45,20 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" -version = "1.0.104" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "asn1-rs" @@ -48,7 +72,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror", + "thiserror 2.0.20", "time", ] @@ -60,8 +84,8 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", - "synstructure 0.13.2", + "syn 2.0.117", + "synstructure", ] [[package]] @@ -72,7 +96,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -106,18 +130,18 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "async-trait" -version = "0.1.92" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 3.0.5", + "syn 2.0.117", ] [[package]] @@ -137,15 +161,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.18.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e" +checksum = "ce2b2dcc879c3bae0d371e77c99f2238400ef24ec001394befa67b6e543add9e" dependencies = [ "aws-lc-sys", "untrusted 0.7.1", @@ -154,9 +178,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.45.0" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27" +checksum = "f09fae7be8bb3174e05c6afdb34199e6dc0c7c04ba9fa237b1967adfbde27483" dependencies = [ "cc", "cmake", @@ -219,6 +243,30 @@ dependencies = [ "tokio", ] +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + +[[package]] +name = "backtrace-ext" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" +dependencies = [ + "backtrace", +] + [[package]] name = "base64" version = "0.22.1" @@ -260,9 +308,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.12.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ "hybrid-array", ] @@ -291,7 +339,7 @@ dependencies = [ "serde_derive", "serde_json", "serde_urlencoded", - "thiserror", + "thiserror 2.0.20", "tokio", "tokio-util", "tower-service", @@ -312,9 +360,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.3" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "byteorder" @@ -330,9 +378,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cc" -version = "1.4.6" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3eb0f42d6c360dc3f8a821f6bf2fdea7f72bfd36b3076eb0e6d1e9e0752fff4" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ "find-msvc-tools", "jobserver", @@ -348,9 +396,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" -version = "0.2.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha20" @@ -359,7 +407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" dependencies = [ "cfg-if", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "rand_core 0.10.1", ] @@ -369,8 +417,12 @@ version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ + "iana-time-zone", + "js-sys", "num-traits", "serde", + "wasm-bindgen", + "windows-link", ] [[package]] @@ -388,6 +440,15 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "core-foundation" version = "0.10.1" @@ -415,9 +476,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] @@ -433,24 +494,24 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.5.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crossbeam-queue" -version = "0.3.14" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e8bd762f7479489c70ed6c768ddca99d7296857de437a68dcb2a94365b3fae" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.23" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" @@ -501,7 +562,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -512,14 +573,14 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "data-encoding" -version = "2.11.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" [[package]] name = "der-parser" @@ -540,6 +601,9 @@ name = "deranged" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] [[package]] name = "digest" @@ -553,24 +617,24 @@ dependencies = [ [[package]] name = "digest" -version = "0.11.3" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" dependencies = [ - "block-buffer 0.12.1", + "block-buffer 0.12.0", "crypto-common 0.2.2", "ctutils", ] [[package]] name = "displaydoc" -version = "0.2.7" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 3.0.5", + "syn 2.0.117", ] [[package]] @@ -600,14 +664,14 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "either" -version = "1.18.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" dependencies = [ "serde", ] @@ -660,10 +724,11 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.4.2" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ + "concurrent-queue", "parking", "pin-project-lite", ] @@ -680,15 +745,21 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "find-msvc-tools" -version = "0.1.12" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flume" @@ -736,12 +807,13 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" -version = "0.3.34" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -750,9 +822,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.34" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -760,15 +832,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.34" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.34" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -788,38 +860,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.34" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" -version = "0.3.34" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 3.0.5", + "syn 2.0.117", ] [[package]] name = "futures-sink" -version = "0.3.34" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.34" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.34" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -849,8 +921,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -867,16 +941,30 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.4.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", "rand_core 0.10.1", + "wasip2", + "wasip3", ] +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + [[package]] name = "gloo-timers" version = "0.3.0" @@ -932,9 +1020,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.17.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "hashlink" @@ -957,7 +1045,7 @@ dependencies = [ "http", "httpdate", "mime", - "sha1 0.10.7", + "sha1 0.10.6", ] [[package]] @@ -996,7 +1084,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ - "digest 0.11.3", + "digest 0.11.2", ] [[package]] @@ -1021,9 +1109,9 @@ dependencies = [ [[package]] name = "http" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", "itoa", @@ -1031,9 +1119,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.1.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", @@ -1041,9 +1129,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.5" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", @@ -1066,18 +1154,18 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hybrid-array" -version = "0.4.15" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" +checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" dependencies = [ "typenum", ] [[package]] name = "hyper" -version = "1.11.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -1116,9 +1204,9 @@ dependencies = [ [[package]] name = "hyper-named-pipe" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fab3637d6b04a8037af8a266fdf6cf92ea957e8c53981a2bf6136572531025bf" +checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" dependencies = [ "hex", "hyper", @@ -1126,6 +1214,7 @@ dependencies = [ "pin-project-lite", "tokio", "tower-service", + "winapi", ] [[package]] @@ -1164,13 +1253,16 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", "futures-util", "http", "http-body", "hyper", + "ipnet", "libc", + "percent-encoding", "pin-project-lite", "socket2", "tokio", @@ -1193,11 +1285,35 @@ dependencies = [ "tower-service", ] +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "icu_collections" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", @@ -1209,9 +1325,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -1222,9 +1338,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -1236,17 +1352,16 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", @@ -1257,15 +1372,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.3.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -1276,6 +1391,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -1295,9 +1416,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -1305,16 +1426,38 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.14.2" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.1", + "hashbrown 0.17.0", "serde", "serde_core", ] +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "iri-string" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + [[package]] name = "itertools" version = "0.14.0" @@ -1332,11 +1475,11 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jobserver" -version = "0.1.35" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.4.3", + "getrandom 0.3.4", "libc", ] @@ -1360,7 +1503,7 @@ dependencies = [ "jsonptr", "serde", "serde_json", - "thiserror", + "thiserror 2.0.20", ] [[package]] @@ -1373,7 +1516,7 @@ dependencies = [ "pest_derive", "regex", "serde_json", - "thiserror", + "thiserror 2.0.20", ] [[package]] @@ -1388,9 +1531,9 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "10.4.0" +version = "10.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc" +checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1" dependencies = [ "aws-lc-rs", "base64 0.22.1", @@ -1401,7 +1544,6 @@ dependencies = [ "serde_json", "signature", "simple_asn1", - "zeroize", ] [[package]] @@ -1417,6 +1559,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "keycloak" +version = "0.0.0" +dependencies = [ + "openshell-testkit", + "serde_json", + "tempfile", + "tokio", +] + [[package]] name = "kube" version = "0.99.0" @@ -1459,7 +1611,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "thiserror", + "thiserror 2.0.20", "tokio", "tokio-util", "tower", @@ -1482,7 +1634,7 @@ dependencies = [ "serde", "serde-value", "serde_json", - "thiserror", + "thiserror 2.0.20", ] [[package]] @@ -1496,7 +1648,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -1521,7 +1673,7 @@ dependencies = [ "pin-project", "serde", "serde_json", - "thiserror", + "thiserror 2.0.20", "tokio", "tokio-util", "tracing", @@ -1533,6 +1685,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" version = "0.2.189" @@ -1547,9 +1705,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libsqlite3-sys" -version = "0.37.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" dependencies = [ "cc", "pkg-config", @@ -1564,9 +1722,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" @@ -1596,14 +1754,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" dependencies = [ "cfg-if", - "digest 0.11.3", + "digest 0.11.2", ] [[package]] name = "memchr" -version = "2.8.3" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "backtrace", + "backtrace-ext", + "cfg-if", + "miette-derive", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "unicode-width 0.1.14", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "mime" @@ -1617,17 +1805,32 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + [[package]] name = "mio" -version = "1.2.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi", "windows-sys 0.61.2", ] +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + [[package]] name = "nix" version = "0.29.0" @@ -1656,7 +1859,7 @@ version = "0.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "962838abbd8dd2cd3844d2208dc502458bba6985f8bf1dc21761b30260fcbd7f" dependencies = [ - "hashbrown 0.17.1", + "hashbrown 0.17.0", "indexmap", "libm", "memchr", @@ -1667,9 +1870,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.8" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", @@ -1677,15 +1880,15 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-integer" -version = "0.1.47" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ "num-traits", ] @@ -1699,6 +1902,35 @@ dependencies = [ "autocfg", ] +[[package]] +name = "oauth2" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e219e79014df21a225b1860a479e2dcd7cbd9130f4defd4bd0e191ea31d67d" +dependencies = [ + "base64 0.22.1", + "chrono", + "getrandom 0.2.17", + "http", + "rand 0.8.6", + "reqwest", + "serde", + "serde_json", + "serde_path_to_error", + "sha2 0.10.9", + "thiserror 1.0.69", + "url", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + [[package]] name = "oid-registry" version = "0.8.1" @@ -1714,17 +1946,69 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "openshell-bootstrap" +version = "0.0.0" +dependencies = [ + "bytes", + "miette", + "openshell-core", + "openshell-crypto", + "rcgen", + "serde", + "serde_json", + "tempfile", + "tokio", + "tracing", +] + [[package]] name = "openshell-conformance" version = "0.0.0" dependencies = [ - "rand 0.9.5", + "rand 0.9.4", "serde", "serde_json", "tempfile", "tokio", ] +[[package]] +name = "openshell-core" +version = "0.0.0" +dependencies = [ + "async-trait", + "base64 0.22.1", + "chrono", + "glob", + "ipnet", + "miette", + "nix", + "openshell-crypto", + "openshell-extension-core", + "openshell-policy-schema", + "prost", + "prost-types", + "protoc-bin-vendored", + "reqwest", + "rustix", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "sha2 0.10.9", + "thiserror 2.0.20", + "tokio", + "tokio-stream", + "tonic", + "tonic-prost", + "tonic-prost-build", + "tonic-types", + "tracing", + "url", + "uuid", +] + [[package]] name = "openshell-crypto" version = "0.0.0" @@ -1737,7 +2021,7 @@ dependencies = [ "rustls", "serde", "sqlx", - "thiserror", + "thiserror 2.0.20", "tonic", "x509-parser", ] @@ -1759,12 +2043,12 @@ dependencies = [ "noyalib", "openshell-crypto", "prost", - "rand 0.9.5", + "rand 0.9.4", "rustls", "rustls-pemfile", "serde", "serde_json", - "sha1 0.10.7", + "sha1 0.10.6", "sha2 0.10.9", "tempfile", "tokio", @@ -1777,41 +2061,120 @@ dependencies = [ ] [[package]] -name = "openshell-test-feature-oci-image" +name = "openshell-extension-core" version = "0.0.0" dependencies = [ - "openshell-conformance", - "serde_json", - "tempfile", + "hyper-util", + "serde", + "thiserror 2.0.20", "tokio", + "tonic", + "tower", ] [[package]] -name = "openshell-test-feature-provider-refresh-keycloak" +name = "openshell-policy-schema" version = "0.0.0" dependencies = [ - "openshell-conformance", - "openshell-e2e", + "miette", + "noyalib", + "serde", "serde_json", - "tempfile", - "tokio", + "serde_path_to_error", + "thiserror 2.0.20", ] [[package]] -name = "openssl-probe" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" - -[[package]] -name = "ordered-float" -version = "2.10.1" +name = "openshell-sdk" +version = "0.0.0" +dependencies = [ + "async-stream", + "async-trait", + "futures", + "hyper", + "hyper-util", + "miette", + "oauth2", + "openshell-core", + "openshell-crypto", + "reqwest", + "rustls", + "serde", + "thiserror 2.0.20", + "tokio", + "tokio-rustls", + "tokio-tungstenite", + "tonic", + "tower", + "tracing", +] + +[[package]] +name = "openshell-test-feature-oci-image" +version = "0.0.0" +dependencies = [ + "openshell-conformance", + "serde_json", + "tempfile", + "tokio", +] + +[[package]] +name = "openshell-test-feature-provider-refresh-keycloak" +version = "0.0.0" +dependencies = [ + "openshell-conformance", + "openshell-e2e", + "serde_json", + "tempfile", + "tokio", +] + +[[package]] +name = "openshell-testkit" +version = "0.0.0" +dependencies = [ + "futures", + "openshell-bootstrap", + "openshell-core", + "openshell-sdk", + "openshell-testkit-macros", + "rand 0.9.4", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "openshell-testkit-macros" +version = "0.0.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "ordered-float" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" dependencies = [ "num-traits", ] +[[package]] +name = "owo-colors" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" + [[package]] name = "parking" version = "2.2.1" @@ -1869,9 +2232,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.9.1" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d45aeb61b4bf818e12d4205f2466f8c4748f85f4fce0146d1c03d69d753f0ad" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" dependencies = [ "memchr", "ucd-trie", @@ -1879,9 +2242,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.9.1" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc5a242e25ed4e7704d0be240f2cfbe20a8c27e7e252d94835be93d92dc39f" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" dependencies = [ "pest", "pest_generator", @@ -1889,44 +2252,56 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.9.1" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abf21475cc3820fe4b2ca2dc2142902f67a02189f3b5b3a229f4febc01a43e5" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "pest_meta" -version = "2.9.1" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adba4db388f687393c18c51348d44a41d870ca9df71a2c98172ea3035dc6936e" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" dependencies = [ "pest", + "sha2 0.10.9", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", ] [[package]] name = "pin-project" -version = "1.1.13" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.13" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -1937,15 +2312,15 @@ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.34" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "potential_utf" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -1965,43 +2340,167 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + [[package]] name = "proc-macro2" -version = "1.0.107" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.14.4" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" dependencies = [ "bytes", "prost-derive", ] +[[package]] +name = "prost-build" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" +dependencies = [ + "heck", + "itertools", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "pulldown-cmark", + "pulldown-cmark-to-cmark", + "regex", + "syn 2.0.117", + "tempfile", +] + [[package]] name = "prost-derive" -version = "0.14.4" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", +] + +[[package]] +name = "prost-types" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" +dependencies = [ + "prost", +] + +[[package]] +name = "protoc-bin-vendored" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1c381df33c98266b5f08186583660090a4ffa0889e76c7e9a5e175f645a67fa" +dependencies = [ + "protoc-bin-vendored-linux-aarch_64", + "protoc-bin-vendored-linux-ppcle_64", + "protoc-bin-vendored-linux-s390_64", + "protoc-bin-vendored-linux-x86_32", + "protoc-bin-vendored-linux-x86_64", + "protoc-bin-vendored-macos-aarch_64", + "protoc-bin-vendored-macos-x86_64", + "protoc-bin-vendored-win32", +] + +[[package]] +name = "protoc-bin-vendored-linux-aarch_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c350df4d49b5b9e3ca79f7e646fde2377b199e13cfa87320308397e1f37e1a4c" + +[[package]] +name = "protoc-bin-vendored-linux-ppcle_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55a63e6c7244f19b5c6393f025017eb5d793fd5467823a099740a7a4222440c" + +[[package]] +name = "protoc-bin-vendored-linux-s390_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dba5565db4288e935d5330a07c264a4ee8e4a5b4a4e6f4e83fad824cc32f3b0" + +[[package]] +name = "protoc-bin-vendored-linux-x86_32" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8854774b24ee28b7868cd71dccaae8e02a2365e67a4a87a6cd11ee6cdbdf9cf5" + +[[package]] +name = "protoc-bin-vendored-linux-x86_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b38b07546580df720fa464ce124c4b03630a6fb83e05c336fea2a241df7e5d78" + +[[package]] +name = "protoc-bin-vendored-macos-aarch_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89278a9926ce312e51f1d999fee8825d324d603213344a9a706daa009f1d8092" + +[[package]] +name = "protoc-bin-vendored-macos-x86_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81745feda7ccfb9471d7a4de888f0652e806d5795b61480605d4943176299756" + +[[package]] +name = "protoc-bin-vendored-win32" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95067976aca6421a523e491fce939a3e65249bac4b977adee0ee9771568e8aa3" + +[[package]] +name = "pulldown-cmark" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" +dependencies = [ + "bitflags", + "memchr", + "unicase", +] + +[[package]] +name = "pulldown-cmark-to-cmark" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90" +dependencies = [ + "pulldown-cmark", ] [[package]] name = "quote" -version = "1.0.47" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -2020,11 +2519,22 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.9.5" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ - "rand_chacha", + "rand_chacha 0.9.0", "rand_core 0.9.5", ] @@ -2035,10 +2545,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ "chacha20", - "getrandom 0.4.3", + "getrandom 0.4.2", "rand_core 0.10.1", ] +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + [[package]] name = "rand_chacha" version = "0.9.0" @@ -2098,9 +2618,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.13.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -2110,9 +2630,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.18" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -2121,9 +2641,48 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.11" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "reqwest" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] [[package]] name = "ring" @@ -2139,11 +2698,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + [[package]] name = "rustc-hash" -version = "2.1.3" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rusticata-macros" @@ -2156,9 +2721,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.5" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", @@ -2169,9 +2734,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.45" +version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ "aws-lc-rs", "log", @@ -2184,9 +2749,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -2205,9 +2770,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.15.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "zeroize", ] @@ -2226,9 +2791,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.23" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -2266,7 +2831,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2307,6 +2872,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + [[package]] name = "serde" version = "1.0.229" @@ -2355,14 +2926,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.151" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", @@ -2371,15 +2942,26 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", + "serde", + "serde_core", +] + [[package]] name = "serde_repr" -version = "0.1.21" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 3.0.5", + "syn 2.0.117", ] [[package]] @@ -2409,9 +2991,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.7" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures 0.2.17", @@ -2425,8 +3007,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" dependencies = [ "cfg-if", - "cpufeatures 0.3.1", - "digest 0.11.3", + "cpufeatures 0.3.0", + "digest 0.11.2", ] [[package]] @@ -2447,15 +3029,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", - "cpufeatures 0.3.1", - "digest 0.11.3", + "cpufeatures 0.3.0", + "digest 0.11.2", ] [[package]] name = "shlex" -version = "2.0.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" @@ -2484,7 +3066,7 @@ checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" dependencies = [ "num-bigint", "num-traits", - "thiserror", + "thiserror 2.0.20", "time", ] @@ -2496,18 +3078,18 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.16.1" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba467056f1b547ed52077911161fc86985becbc60e8e1857c8a144dab0def891" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ "serde", ] [[package]] name = "socket2" -version = "0.6.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", "windows-sys 0.61.2", @@ -2563,7 +3145,7 @@ dependencies = [ "serde_json", "sha2 0.10.9", "smallvec", - "thiserror", + "thiserror 2.0.20", "tokio", "tokio-stream", "tracing", @@ -2581,7 +3163,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2603,8 +3185,8 @@ dependencies = [ "sqlx-core", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.119", - "thiserror", + "syn 2.0.117", + "thiserror 2.0.20", "tokio", "url", ] @@ -2619,7 +3201,7 @@ dependencies = [ "byteorder", "bytes", "crc", - "digest 0.11.3", + "digest 0.11.2", "dotenvy", "either", "futures-core", @@ -2631,7 +3213,7 @@ dependencies = [ "sha1 0.11.0", "sha2 0.11.0", "sqlx-core", - "thiserror", + "thiserror 2.0.20", "tracing", ] @@ -2665,7 +3247,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 2.0.20", "tracing", "whoami", ] @@ -2689,7 +3271,7 @@ dependencies = [ "percent-encoding", "serde", "sqlx-core", - "thiserror", + "thiserror 2.0.20", "tracing", "url", ] @@ -2723,11 +3305,32 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "supports-color" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" +dependencies = [ + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91" + +[[package]] +name = "supports-unicode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" + [[package]] name = "syn" -version = "2.0.119" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -2750,27 +3353,19 @@ name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", + "futures-core", ] [[package]] name = "synstructure" -version = "0.14.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 3.0.5", + "syn 2.0.117", ] [[package]] @@ -2780,19 +3375,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.3", + "getrandom 0.4.2", "once_cell", "rustix", "windows-sys 0.61.2", ] +[[package]] +name = "terminal_size" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" +dependencies = [ + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "textwrap" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" +dependencies = [ + "unicode-linebreak", + "unicode-width 0.2.2", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.20", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -2808,11 +3443,12 @@ dependencies = [ [[package]] name = "time" -version = "0.3.55" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", "serde_core", @@ -2822,15 +3458,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.9" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.32" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -2838,9 +3474,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -2848,15 +3484,24 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.13.3" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.53.1" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -2871,20 +3516,20 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.2" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 3.0.5", + "syn 2.0.117", ] [[package]] name = "tokio-rustls" -version = "0.26.6" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -2892,15 +3537,31 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.19" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" +dependencies = [ + "futures-util", + "log", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.7.19" @@ -2935,6 +3596,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", + "rustls-native-certs", "socket2", "sync_wrapper", "tokio", @@ -2946,6 +3608,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "tonic-build" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "tonic-prost" version = "0.14.6" @@ -2957,6 +3631,33 @@ dependencies = [ "tonic", ] +[[package]] +name = "tonic-prost-build" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn 2.0.117", + "tempfile", + "tonic-build", +] + +[[package]] +name = "tonic-types" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab1b02061f83d519bba3caa167f88f261ef05720ab8ebc954ade70de3348e8" +dependencies = [ + "prost", + "prost-types", + "tonic", +] + [[package]] name = "tower" version = "0.5.3" @@ -2978,17 +3679,20 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.11" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "base64 0.22.1", "bitflags", "bytes", + "futures-util", "http", "http-body", + "iri-string", "mime", "pin-project-lite", + "tower", "tower-layer", "tower-service", "tracing", @@ -3026,7 +3730,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -3044,6 +3748,25 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.9.4", + "rustls", + "rustls-pki-types", + "sha1 0.10.6", + "thiserror 2.0.20", + "utf-8", +] + [[package]] name = "typenum" version = "1.20.1" @@ -3056,6 +3779,12 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + [[package]] name = "unicode-bidi" version = "0.3.18" @@ -3068,6 +3797,12 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + [[package]] name = "unicode-normalization" version = "0.1.25" @@ -3083,6 +3818,24 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "unsafe-libyaml" version = "0.2.11" @@ -3111,14 +3864,32 @@ dependencies = [ "idna", "percent-encoding", "serde", + "serde_derive", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "uuid" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +dependencies = [ + "getrandom 0.4.2", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -3148,11 +3919,20 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.4+wasi-0.2.12" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] @@ -3168,6 +3948,16 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ef4c5d3d2cdf5c54f4231181768f5510842e350db025faf1f7163b1030ed928" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.128" @@ -3200,6 +3990,50 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "web-sys" +version = "0.3.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbddc4a036f00ec4f18c83445bd3115cb306a91da554919a099d9222fe4a7f8" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "1.0.10" @@ -3237,12 +4071,65 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -3325,17 +4212,105 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + [[package]] name = "writeable" -version = "0.6.4" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "x509-parser" @@ -3351,7 +4326,7 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror", + "thiserror 2.0.20", "time", ] @@ -3367,9 +4342,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -3378,55 +4353,55 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33811428bee40dbceb6d545e95754741d17a6aef9a4849f0fd62e2ba4f412a78" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 3.0.5", - "synstructure 0.14.0", + "syn 2.0.117", + "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.57" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d35102a9f36d089ccae9e4c6802bc118be4487b80aaffc0ab4e0cf5ce92d2873" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.57" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c01f5ab44258da43cf276c74a2763db2ff3969c9c652c3f2de07041d0b2bc" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "zerofrom" -version = "0.1.8" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.8" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 3.0.5", - "synstructure 0.14.0", + "syn 2.0.117", + "synstructure", ] [[package]] @@ -3434,26 +4409,12 @@ name = "zeroize" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] [[package]] name = "zerotrie" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -3462,9 +4423,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.8" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -3473,17 +4434,17 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.6" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 3.0.5", + "syn 2.0.117", ] [[package]] name = "zmij" -version = "1.0.23" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/tests/suites/features/Cargo.toml b/tests/suites/features/Cargo.toml index 9259450a16..f34f09db2f 100644 --- a/tests/suites/features/Cargo.toml +++ b/tests/suites/features/Cargo.toml @@ -3,4 +3,4 @@ [workspace] resolver = "2" -members = ["oci-image", "provider-refresh/keycloak"] +members = ["keycloak", "oci-image", "provider-refresh/keycloak"] diff --git a/tests/suites/features/keycloak/Cargo.toml b/tests/suites/features/keycloak/Cargo.toml new file mode 100644 index 0000000000..03e4b8d68f --- /dev/null +++ b/tests/suites/features/keycloak/Cargo.toml @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +[package] +name = "keycloak" +description = "Features suites: behavior that needs a Keycloak OIDC issuer" +version = "0.0.0" +edition = "2024" +rust-version = "1.94" +license = "Apache-2.0" +repository = "https://github.com/NVIDIA/OpenShell" +publish = false + +[dependencies] +openshell-testkit = { path = "../../../testkit/testkit" } +serde_json = "1" +tempfile = "3" +tokio = { version = "1.43", features = ["io-util", "process"] } diff --git a/tests/suites/features/keycloak/src/lib.rs b/tests/suites/features/keycloak/src/lib.rs new file mode 100644 index 0000000000..1915031bb3 --- /dev/null +++ b/tests/suites/features/keycloak/src/lib.rs @@ -0,0 +1,278 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! A Keycloak fixture for suites that need an OIDC issuer. +//! +//! The environment runs Keycloak and publishes how to reach it in +//! `OPENSHELL_TEST_KEYCLOAK_*` variables. Under `openshell-test-runner`, the +//! tmachine `ubuntu-docker-rootful-keycloak` environment does that +//! (`tests/tmachine/ansible/playbooks/keycloak.yaml`); against your own +//! deployment, set them yourself: +//! +//! | Variable | Example | +//! |---|---| +//! | `OPENSHELL_TEST_KEYCLOAK_ISSUER` | `http://127.0.0.1:8180/realms/openshell` | +//! | `OPENSHELL_TEST_KEYCLOAK_CLIENT_ID` | `openshell-cli` | +//! | `OPENSHELL_TEST_KEYCLOAK_USERNAME` | `admin@test` | +//! | `OPENSHELL_TEST_KEYCLOAK_PASSWORD` | `admin` | +//! +//! The issuer must be reachable from the test process. The client must allow +//! password grants. A missing variable fails the test; it never skips it. +//! The fixture waits for the realm to answer, since Keycloak may still be +//! starting when the tests begin. +//! +//! A test builds the fixture from its testkit [`Context`]: +//! +//! ```ignore +//! #[testkit::test] +//! async fn example(cx: &mut testkit::Context) -> testkit::Result { +//! let kc = keycloak::KeycloakContext::new(cx).await?; +//! let grant = kc.keycloak().password_grant().await?; +//! kc.cli(["status"]).await?.success()?; // Context methods still work +//! Ok(()) +//! } +//! ``` +//! +//! The fixture owns no Keycloak state, so it has nothing to clean up. Tests +//! that create resources in Keycloak or `OpenShell` must remove them. + +use std::fmt; +use std::ops::{Deref, DerefMut}; +use std::process::Stdio; +use std::time::Duration; + +use serde_json::Value; +use testkit::{Context, Error, Poll, Result, ResultExt as _, poll_until}; +use tokio::io::AsyncWriteExt as _; +use tokio::process::Command; + +pub const ISSUER_ENV: &str = "OPENSHELL_TEST_KEYCLOAK_ISSUER"; +pub const CLIENT_ID_ENV: &str = "OPENSHELL_TEST_KEYCLOAK_CLIENT_ID"; +pub const USERNAME_ENV: &str = "OPENSHELL_TEST_KEYCLOAK_USERNAME"; +pub const PASSWORD_ENV: &str = "OPENSHELL_TEST_KEYCLOAK_PASSWORD"; +/// How long Keycloak has to start answering, e.g. after the environment boots. +pub const READY_TIMEOUT: Duration = Duration::from_mins(3); + +/// How to reach the environment's Keycloak realm, and a user in it. +#[derive(Clone)] +pub struct Keycloak { + issuer: String, + client_id: String, + username: String, + password: String, +} + +/// Tokens from one Keycloak login. +#[derive(Clone)] +pub struct Grant { + pub access_token: String, + pub refresh_token: String, +} + +/// A testkit [`Context`] plus the environment's Keycloak. Derefs to the +/// `Context`, so its methods work unchanged. +pub struct KeycloakContext<'a> { + cx: &'a mut Context, + keycloak: Keycloak, +} + +impl<'a> KeycloakContext<'a> { + /// Read the Keycloak configuration from the environment and wait until + /// the realm answers. + pub async fn new(cx: &'a mut Context) -> Result { + let keycloak = Keycloak::from_env()?; + keycloak.wait_ready().await?; + Ok(Self { cx, keycloak }) + } + + pub fn keycloak(&self) -> &Keycloak { + &self.keycloak + } +} + +impl Deref for KeycloakContext<'_> { + type Target = Context; + + fn deref(&self) -> &Context { + self.cx + } +} + +impl DerefMut for KeycloakContext<'_> { + fn deref_mut(&mut self) -> &mut Context { + self.cx + } +} + +impl Keycloak { + /// Read `OPENSHELL_TEST_KEYCLOAK_*`. Fails naming the first missing + /// variable. + pub fn from_env() -> Result { + Ok(Self { + issuer: required(ISSUER_ENV)?.trim_end_matches('/').to_string(), + client_id: required(CLIENT_ID_ENV)?, + username: required(USERNAME_ENV)?, + password: required(PASSWORD_ENV)?, + }) + } + + /// The realm's issuer URL, e.g. `http://127.0.0.1:8180/realms/openshell`. + pub fn issuer(&self) -> &str { + &self.issuer + } + + pub fn client_id(&self) -> &str { + &self.client_id + } + + /// Wait until the realm's discovery document is served. + pub async fn wait_ready(&self) -> Result { + let url = format!("{}/.well-known/openid-configuration", self.issuer); + poll_until( + &format!("Keycloak realm at {}", self.issuer), + READY_TIMEOUT, + Duration::from_secs(2), + async || { + let output = Command::new("curl") + .args([ + "--fail", + "--silent", + "--show-error", + "--output", + "/dev/null", + &url, + ]) + .output() + .await + .map_err(|error| Error::from_error(&error)) + .context("run curl")?; + Ok(if output.status.success() { + Poll::Ready(()) + } else { + Poll::Pending(String::from_utf8_lossy(&output.stderr).trim().to_string()) + }) + }, + ) + .await + } + + pub fn token_endpoint(&self) -> String { + format!("{}/protocol/openid-connect/token", self.issuer) + } + + /// Log in as the configured user with the password grant. + pub async fn password_grant(&self) -> Result { + let client_id = format!("client_id={}", self.client_id); + let username = format!("username={}", self.username); + let stdout = post_form( + &self.token_endpoint(), + &["grant_type=password", &client_id, &username, "scope=openid"], + ("password", &self.password), + ) + .await + .context("Keycloak password grant")?; + + let response: Value = serde_json::from_slice(&stdout) + .map_err(|error| Error::from_error(&error)) + .context("decode Keycloak grant response")?; + let token = |name: &str| { + response + .get(name) + .and_then(Value::as_str) + .filter(|value| !value.is_empty()) + .map(str::to_string) + .ok_or_else(|| Error::msg(format!("Keycloak grant response has no {name}"))) + }; + Ok(Grant { + access_token: token("access_token")?, + refresh_token: token("refresh_token")?, + }) + } + + /// End the Keycloak session behind `refresh_token`, so refreshing with it + /// fails with `invalid_grant`. + pub async fn revoke(&self, refresh_token: &str) -> Result { + let client_id = format!("client_id={}", self.client_id); + post_form( + &format!("{}/protocol/openid-connect/logout", self.issuer), + &[&client_id], + ("refresh_token", refresh_token), + ) + .await + .context("Keycloak logout")?; + Ok(()) + } +} + +fn required(name: &str) -> Result { + std::env::var(name) + .ok() + .filter(|value| !value.is_empty()) + .ok_or_else(|| { + Error::msg(format!( + "{name} is not set; this suite needs a Keycloak realm (see the keycloak crate docs)" + )) + }) +} + +/// POST a URL-encoded form with curl and return the response body. `secret` +/// goes through stdin, so it isn't in curl's arguments or in errors. +async fn post_form(url: &str, fields: &[&str], secret: (&str, &str)) -> Result> { + let mut command = Command::new("curl"); + command.args([ + "--fail-with-body", + "--silent", + "--show-error", + "--request", + "POST", + url, + ]); + for field in fields { + command.args(["--data-urlencode", field]); + } + command.args(["--data-urlencode", &format!("{}@-", secret.0)]); + let mut child = command + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .kill_on_drop(true) + .spawn() + .map_err(|error| Error::from_error(&error)) + .context("run curl")?; + let mut stdin = child.stdin.take().expect("stdin is piped"); + stdin + .write_all(secret.1.as_bytes()) + .await + .map_err(|error| Error::from_error(&error)) + .context("write request body")?; + drop(stdin); + let output = child + .wait_with_output() + .await + .map_err(|error| Error::from_error(&error)) + .context("wait for curl")?; + testkit::ensure!( + output.status.success(), + "POST {url} failed ({}): {}{}", + output.status, + String::from_utf8_lossy(&output.stdout).trim(), + String::from_utf8_lossy(&output.stderr).trim() + ); + Ok(output.stdout) +} + +impl fmt::Debug for Keycloak { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Keycloak") + .field("issuer", &self.issuer) + .field("client_id", &self.client_id) + .field("username", &self.username) + .finish_non_exhaustive() + } +} + +impl fmt::Debug for Grant { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Grant").finish_non_exhaustive() + } +} diff --git a/tests/suites/features/keycloak/tests/provider_refresh.rs b/tests/suites/features/keycloak/tests/provider_refresh.rs new file mode 100644 index 0000000000..0cc65b662e --- /dev/null +++ b/tests/suites/features/keycloak/tests/provider_refresh.rs @@ -0,0 +1,178 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Provider OAuth refresh against Keycloak. +//! +//! Keycloak is only the provider's token issuer here; the CLI still reaches +//! the gateway the usual way. Ported from +//! `tests/suites/features/provider-refresh/keycloak`, which tmachine's +//! `provider-refresh` testsuite runs until the required lanes switch. + +use std::io::Write as _; + +use keycloak::KeycloakContext; +use testkit::{CliOutput, Context, Error, ResultExt as _}; + +const CREDENTIAL_KEY: &str = "KEYCLOAK_ACCESS_TOKEN"; + +/// A provider refreshes a valid Keycloak grant. Once Keycloak revokes the +/// grant, the next refresh fails with `invalid_grant` and the provider reports +/// that the user must reauthorize. +#[testkit::test] +async fn revoked_refresh_grant_requires_user_reauthorization(cx: &mut Context) -> testkit::Result { + let kc = KeycloakContext::new(cx).await?; + let provider = kc.name("kc-refresh"); + let profile_id = kc.name("kc-refresh-profile"); + let grant = kc.keycloak().password_grant().await?; + let profile = write_profile(&profile_id, kc.keycloak())?; + let profile_path = profile.path().to_string_lossy().into_owned(); + + let result = async { + kc.cli(["profile", "import", "--file", &profile_path]) + .await? + .success()?; + kc.cli_with_env( + &[(CREDENTIAL_KEY, &grant.access_token)], + [ + "provider", + "create", + "--name", + &provider, + "--type", + &profile_id, + "--credential", + CREDENTIAL_KEY, + ], + ) + .await? + .success()?; + let client_id = format!("client_id={}", kc.keycloak().client_id()); + kc.cli_with_env( + &[("KEYCLOAK_REFRESH_TOKEN", &grant.refresh_token)], + [ + "provider", + "refresh", + "configure", + &provider, + "--credential-key", + CREDENTIAL_KEY, + "--strategy", + "oauth2-refresh-token", + "--material", + &client_id, + "--secret-material-env", + "refresh_token=KEYCLOAK_REFRESH_TOKEN", + ], + ) + .await? + .success()?; + + let refresh = |verb: &'static str| { + [ + "provider", + "refresh", + verb, + provider.as_str(), + "--credential-key", + CREDENTIAL_KEY, + ] + }; + + kc.cli(refresh("rotate")).await?.success()?; + let status = kc.cli(refresh("status")).await?.success()?; + testkit::ensure!( + combined(&status).contains("refreshed"), + "a valid refresh did not reach the refreshed state:\n{}", + combined(&status) + ); + + kc.keycloak().revoke(&grant.refresh_token).await?; + let rotate = kc.cli(refresh("rotate")).await?.failure()?; + testkit::ensure!( + combined(&rotate).contains("invalid_grant"), + "a revoked refresh failed without invalid_grant:\n{}", + combined(&rotate) + ); + + let status = combined(&kc.cli(refresh("status")).await?.success()?); + for expected in [ + "reauthorization_required", + "reauthorize", + "oauth_invalid_grant", + ] { + testkit::ensure!( + status.contains(expected), + "the revoked refresh status omits {expected}:\n{}", + status + ); + } + // A parked refresh is scheduled at i64::MAX; it must not render as a date. + testkit::ensure!( + !status.contains("292278994"), + "the parked refresh rendered its scheduling sentinel as a date:\n{}", + status + ); + Ok(()) + } + .await; + + // testkit cleans up sandboxes, not providers or profiles, so remove them + // here whether or not the test passed. A panic or a killed test process + // skips this; the names are unique to the run, so leftovers don't collide. + let _ = kc.cli(["provider", "delete", &provider]).await; + let _ = kc.cli(["profile", "delete", &profile_id]).await; + result +} + +fn combined(output: &CliOutput) -> String { + format!("{}{}", output.stdout, output.stderr) +} + +fn write_profile( + profile_id: &str, + keycloak: &keycloak::Keycloak, +) -> testkit::Result { + let issuer_token_url = keycloak.token_endpoint(); + let profile = format!( + r#"id: {profile_id} +display_name: Keycloak provider refresh test +category: other +credentials: + - name: access_token + env_vars: [{CREDENTIAL_KEY}] + required: true + auth_style: bearer + header_name: authorization + refresh: + strategy: oauth2_refresh_token + token_url: {issuer_token_url} + scopes: [openid] + refresh_before_seconds: 60 + max_lifetime_seconds: 3600 + material: + - name: client_id + required: true + - name: refresh_token + required: true + secret: true +endpoints: + - host: keycloak.test.invalid + port: 443 + protocol: rest + access: read-only + enforcement: enforce +binaries: + - /usr/bin/curl +"# + ); + let mut file = tempfile::Builder::new() + .suffix(".yaml") + .tempfile() + .map_err(|error| Error::from_error(&error)) + .context("create provider profile")?; + file.write_all(profile.as_bytes()) + .and_then(|()| file.flush()) + .map_err(|error| Error::from_error(&error)) + .context("write provider profile")?; + Ok(file) +} From df2bcbd332a27e575dba7413b368b82abbd0fdc3 Mon Sep 17 00:00:00 2001 From: Matthew Grossman Date: Fri, 23 Oct 2026 15:48:27 -0700 Subject: [PATCH 5/5] ci(tests): run the Keycloak features suite in E2E Suites Add a matrix row for features/keycloak on ubuntu-docker-rootful-keycloak, include the Keycloak realm in the tmachine disk cache key, and document environments that provide services in TESTING.md. Signed-off-by: Matthew Grossman --- .github/workflows/e2e-suites.yml | 7 ++++++- TESTING.md | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e-suites.yml b/.github/workflows/e2e-suites.yml index eb0b8807a2..3511b27a79 100644 --- a/.github/workflows/e2e-suites.yml +++ b/.github/workflows/e2e-suites.yml @@ -48,6 +48,11 @@ jobs: family: conformance package: sandbox runner: ubuntu-24.04 + - environment: ubuntu-docker-rootful-keycloak + installer: deb + family: features + package: keycloak + runner: ubuntu-24.04 runs-on: ${{ matrix.runner }} timeout-minutes: 90 steps: @@ -77,7 +82,7 @@ jobs: # actions/cache doesn't save after an exact key hit, so a fixed key # would rebuild the changed layers on every run. Key on the playbooks # and fall back to the newest entry for the same runner. - key: tmachine-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('tests/tmachine/ansible/**', 'tests/tmachine/images.nix') }} + key: tmachine-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('tests/tmachine/ansible/**', 'tests/tmachine/images.nix', 'scripts/keycloak-realm.json') }} restore-keys: | tmachine-${{ runner.os }}-${{ runner.arch }}- diff --git a/TESTING.md b/TESTING.md index 677fb3adac..8787c8f296 100644 --- a/TESTING.md +++ b/TESTING.md @@ -204,6 +204,24 @@ an explicit matrix and runs the runner once per row. Branch E2E calls it when the `test:e2e` label is set. It is advisory for now. To run a suite in another environment on CI, add a row. +**Environments with services.** A suite that needs something besides the +gateway, such as an OIDC issuer, runs in a tmachine environment that provides +it. The environment's setup starts the service (with a restart policy, since +setup is cached as a disk) and writes how to reach it as `OPENSHELL_TEST_*` +lines in `/etc/openshell-test/env.d/.env`. The runner passes those +variables to the tests and rejects names without that prefix. A suite-local +fixture reads them with plain environment variables, so you can run the suite +against your own deployment by setting them yourself. See the +`ubuntu-docker-rootful-keycloak` environment in `tests/tmachine/config.nix`, +`tests/tmachine/ansible/playbooks/keycloak.yaml` and +`tests/suites/features/keycloak`: + +```shell +nix run .#openshell-test-runner -- \ + --environment ubuntu-docker-rootful-keycloak --installer deb \ + --family features --package keycloak +``` + The older conformance, feature and driver lanes in `.github/workflows/` still run through the tmachine testsuites in `tests/tmachine/config.nix`. They move to the runner as their suites move to testkit.