deps: bump rand 0.8 → 0.9 (#163)

## Summary
- Bumps `rand` from 0.8 to 0.9 to resolve Dependabot alert #16 (low
severity: "Rand is unsound with a custom logger using rand::rng()",
fixed in 0.9.3).
- Migrates call sites to the renamed 0.9 APIs.

## API changes applied
- `rand::thread_rng()` → `rand::rng()`
- `Rng::gen_range(..)` → `Rng::random_range(..)`
- `Rng::gen::<T>()` → `Rng::random::<T>()`
- `OsRng.fill_bytes(..)` → `OsRng.try_fill_bytes(..).expect("OS RNG")` —
in 0.9 `OsRng` implements `TryRngCore` instead of `RngCore` directly.

## Test plan
- [x] `cargo build --workspace`
- [x] `cargo nextest run -p fabro-util -p fabro-server -p fabro-workflow
-p fabro-oauth` (1270 passed)
- [x] `cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D
warnings`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-04-17 07:57:10 -04:00 committed by GitHub
parent 31b4bd801e
commit 5946047202
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 20 additions and 20 deletions

14
Cargo.lock generated
View file

@ -1620,7 +1620,7 @@ dependencies = [
"paste",
"predicates",
"progenitor-client",
"rand 0.8.5",
"rand 0.9.2",
"regex",
"ring",
"rustls",
@ -1788,7 +1788,7 @@ dependencies = [
"http",
"httpmock",
"insta",
"rand 0.8.5",
"rand 0.9.2",
"serde",
"serde_json",
"thiserror 2.0.18",
@ -1843,7 +1843,7 @@ dependencies = [
"hex",
"httpmock",
"open",
"rand 0.8.5",
"rand 0.9.2",
"serde",
"serde_json",
"sha2",
@ -1896,7 +1896,7 @@ dependencies = [
"futures",
"git2",
"glob",
"rand 0.8.5",
"rand 0.9.2",
"serde",
"serde_json",
"shlex",
@ -1956,7 +1956,7 @@ dependencies = [
"multer",
"object_store",
"openapiv3",
"rand 0.8.5",
"rand 0.9.2",
"regex",
"rustls",
"rustls-pemfile",
@ -2130,7 +2130,7 @@ dependencies = [
"console 0.15.11",
"dirs",
"insta",
"rand 0.8.5",
"rand 0.9.2",
"regex",
"serde",
"serde_json",
@ -2205,7 +2205,7 @@ dependencies = [
"mime_guess",
"object_store",
"predicates",
"rand 0.8.5",
"rand 0.9.2",
"regex",
"scopeguard",
"serde",

View file

@ -20,7 +20,7 @@ tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.13", default-features = false, features = ["json", "stream", "rustls", "query", "form", "multipart"] }
ulid = "1"
uuid = { version = "1", features = ["v4", "v7", "v8"] }
rand = "0.8"
rand = "0.9"
dotenvy = "0.15"
futures = "0.3"
tokio-stream = "0.1"

View file

@ -933,10 +933,10 @@ impl GitHubAppOwner {
if let Some(user) = username {
format!("{user}-fabro")
} else {
let mut rng = rand::thread_rng();
let mut rng = rand::rng();
let suffix: String = (0..6).fold(String::with_capacity(6), |mut s, _| {
use std::fmt::Write;
let _ = write!(s, "{:x}", rng.gen::<u8>() % 16);
let _ = write!(s, "{:x}", rng.random::<u8>() % 16);
s
});
format!("Fabro-{suffix}")

View file

@ -186,7 +186,7 @@ impl DaytonaSandbox {
format!(
"fabro-{}-{:04x}",
chrono::Utc::now().format("%Y%m%d-%H%M%S"),
rand::thread_rng().gen_range(0..0x10000u32),
rand::rng().random_range(0..0x10000u32),
)
};
let (network_block_all, network_allow_list) = match &self.config.network {

View file

@ -89,7 +89,7 @@ use fabro_workflow::run_status::{
};
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation};
use object_store::memory::InMemory as MemoryObjectStore;
use rand::RngCore;
use rand::TryRngCore;
use rand::rngs::OsRng;
use sha2::{Digest, Sha256};
use tempfile::NamedTempFile;
@ -740,7 +740,7 @@ impl AppState {
fn artifact_upload_token_keys() -> ArtifactUploadTokenKeys {
let mut secret = [0_u8; 32];
OsRng.fill_bytes(&mut secret);
OsRng.try_fill_bytes(&mut secret).expect("OS RNG");
let mut validation = Validation::new(Algorithm::HS256);
validation.set_required_spec_claims(&["iss", "iat", "exp"]);

View file

@ -34,7 +34,7 @@ impl BackoffPolicy {
};
if self.jitter {
// Apply jitter: random factor in [0.5, 1.5)
let jitter_factor = rand::thread_rng().gen_range(0.5..1.5);
let jitter_factor = rand::rng().random_range(0.5..1.5);
capped.mul_f64(jitter_factor)
} else {
capped

View file

@ -3,7 +3,7 @@ use std::io::Write as _;
use std::path::Path;
use anyhow::{Result, anyhow};
use rand::RngCore;
use rand::TryRngCore;
use rand::rngs::OsRng;
pub const DEV_TOKEN_PREFIX: &str = "fabro_dev_";
@ -13,7 +13,7 @@ const DEV_TOKEN_LEN: usize = DEV_TOKEN_PREFIX.len() + DEV_TOKEN_HEX_LEN;
pub fn generate_dev_token() -> String {
let mut bytes = [0_u8; DEV_TOKEN_RANDOM_BYTES];
OsRng.fill_bytes(&mut bytes);
OsRng.try_fill_bytes(&mut bytes).expect("OS RNG");
let mut token = String::with_capacity(DEV_TOKEN_LEN);
token.push_str(DEV_TOKEN_PREFIX);

View file

@ -3,8 +3,8 @@ use rand::Rng;
const MIN_SESSION_SECRET_LEN: usize = 64;
pub fn generate_session_secret() -> String {
let mut rng = rand::thread_rng();
let bytes: [u8; 32] = rng.gen();
let mut rng = rand::rng();
let bytes: [u8; 32] = rng.random();
let mut output = String::with_capacity(bytes.len() * 2);
for byte in bytes {
use std::fmt::Write as _;

View file

@ -197,8 +197,8 @@ fn weighted_random<'a>(edges: &[&'a GvEdge]) -> Option<&'a GvEdge> {
})
.collect();
let total: f64 = weights.iter().sum();
let mut rng = rand::thread_rng();
let mut roll: f64 = rng.gen_range(0.0..total);
let mut rng = rand::rng();
let mut roll: f64 = rng.random_range(0.0..total);
for (i, &w) in weights.iter().enumerate() {
roll -= w;
if roll < 0.0 {