-
Notifications
You must be signed in to change notification settings - Fork 4
✨ Headless load tests #3100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ Headless load tests #3100
Changes from 6 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,10 +52,9 @@ pub async fn insert_cast_vote( | |
| ErrorCode::Unauthorized, | ||
| ) | ||
| })?; | ||
| let auth_time = &claims.auth_time.or_else(|| { | ||
| matches!(voting_channel, VotingStatusChannel::TELEPHONE) | ||
| .then_some(claims.iat) | ||
| }); | ||
| let auth_time = &claims | ||
| .auth_time | ||
| .or_else(|| auth_time_iat_fallback_allowed(voting_channel).then_some(claims.iat)); | ||
|
|
||
| info!("insert-cast-vote: starting"); | ||
|
|
||
|
|
@@ -319,3 +318,59 @@ pub async fn insert_cast_vote( | |
|
|
||
| Ok(Json(inserted_cast_vote)) | ||
| } | ||
|
|
||
| /// Whether a missing `auth_time` claim may fall back to `iat` for the | ||
| /// given voting channel. | ||
| /// | ||
| /// Always allowed for `TELEPHONE`: that channel already has no | ||
| /// browser-derived `auth_time` to rely on. `ONLINE` real voters always go | ||
| /// through a browser and get a genuine `auth_time` for free — Keycloak | ||
| /// only ever sets the `AUTH_TIME` session note on the `authorization_code` | ||
| /// flow, never on `grant_type=password` — so requiring it there doubles | ||
| /// as an implicit "this came from a browser" check. This fallback is an | ||
| /// explicit, env-gated escape hatch from that for non-browser tooling | ||
| /// (e.g. `headless-load-test`'s password-grant voter login, | ||
| /// `packages/headless-load-test/src/vote/cast.rs`) against environments | ||
| /// that opt in via `HARVEST_ALLOW_ONLINE_AUTH_TIME_IAT_FALLBACK=true` — | ||
| /// unset (the default) preserves the strict, browser-only requirement, and | ||
| /// no real deployment's config sets it. | ||
| fn auth_time_iat_fallback_allowed(voting_channel: VotingStatusChannel) -> bool { | ||
| match voting_channel { | ||
| VotingStatusChannel::TELEPHONE => true, | ||
| VotingStatusChannel::ONLINE => { | ||
| std::env::var("HARVEST_ALLOW_ONLINE_AUTH_TIME_IAT_FALLBACK") | ||
| .map(|value| value == "true") | ||
| .unwrap_or(false) | ||
| } | ||
| VotingStatusChannel::KIOSK | VotingStatusChannel::EARLY_VOTING => false, | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| const ENV_VAR: &str = "HARVEST_ALLOW_ONLINE_AUTH_TIME_IAT_FALLBACK"; | ||
|
|
||
| // One test, run sequentially, so concurrent `cargo test` threads don't | ||
| // race on this shared process-global env var. | ||
| #[test] | ||
| fn auth_time_iat_fallback_is_gated_per_channel_and_env_var() { | ||
| std::env::remove_var(ENV_VAR); | ||
| assert!(auth_time_iat_fallback_allowed(VotingStatusChannel::TELEPHONE)); | ||
| assert!(!auth_time_iat_fallback_allowed(VotingStatusChannel::ONLINE)); | ||
| assert!(!auth_time_iat_fallback_allowed(VotingStatusChannel::KIOSK)); | ||
| assert!(!auth_time_iat_fallback_allowed( | ||
| VotingStatusChannel::EARLY_VOTING | ||
| )); | ||
|
|
||
| std::env::set_var(ENV_VAR, "true"); | ||
| assert!(auth_time_iat_fallback_allowed(VotingStatusChannel::ONLINE)); | ||
| assert!(auth_time_iat_fallback_allowed(VotingStatusChannel::TELEPHONE)); | ||
|
|
||
| std::env::set_var(ENV_VAR, "false"); | ||
| assert!(!auth_time_iat_fallback_allowed(VotingStatusChannel::ONLINE)); | ||
|
|
||
| std::env::remove_var(ENV_VAR); | ||
| } | ||
| } | ||
|
Comment on lines
+349
to
+376
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- repository guidance ---'
find /tmp/coderabbit-repo-knowledge/sequentech-step-58f97436 -type f -name '*.md' -print
printf '%s\n' '--- target file outline ---'
ast-grep outline packages/harvest/src/routes/insert_cast_vote.rs
printf '%s\n' '--- target test and helper ---'
sed -n '1,110p' packages/harvest/src/routes/insert_cast_vote.rs
sed -n '330,390p' packages/harvest/src/routes/insert_cast_vote.rs
printf '%s\n' '--- scoped guidance ---'
for f in /tmp/coderabbit-repo-knowledge/sequentech-step-58f97436/*/*.md; do
case "$f" in
*/learnings/*) ;;
*) head -200 "$f";;
esac
done
printf '%s\n' '--- relevant learnings ---'
for f in /tmp/coderabbit-repo-knowledge/sequentech-step-58f97436/learnings/*.md; do
[ -e "$f" ] && head -200 "$f"
doneRepository: sequentech/step Length of output: 16338 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- harvest manifest and workspace edition ---'
find packages -maxdepth 3 -name Cargo.toml -print | sort | head -80
for f in Cargo.toml packages/harvest/Cargo.toml; do
if [ -f "$f" ]; then
printf '\n--- %s ---\n' "$f"
rg -n -C 3 '^(edition|rust-version)\s*=|^\[package\]|^\[workspace\]' "$f"
fi
done
printf '%s\n' '--- test serialization helpers and environment access ---'
rg -n -C 3 'serial_test|mutex|OnceLock|set_var|remove_var|HARVEST_ALLOW_ONLINE_AUTH_TIME_IAT_FALLBACK' packages/harvest tests Cargo.toml packages/harvest/Cargo.toml 2>/dev/null || trueRepository: sequentech/step Length of output: 4951 🌐 Web query:
💡 Result: In the Rust 2024 Edition, the functions std::env::set_var and std::env::remove_var are marked as unsafe [1][2]. This change was introduced because these functions can be unsound in multithreaded programs on many operating systems, as they modify the process's environment variable block—a shared resource that is not thread-safe and can be accessed by various C library functions or other threads without synchronization [1][3][4]. Key points regarding this change and concurrency safety: 1. Safety Requirement: Because the environment is a global, shared resource that many external libraries may read concurrently (often without the user's knowledge), it is generally not possible to guarantee that no other thread is reading or writing the environment during a call to set_var or remove_var [3][4]. Consequently, the only sound way to use these functions in multithreaded programs on most platforms is to avoid them entirely [3][4]. 2. Edition-Specific Behavior: While marked as unsafe in the 2024 Edition, these functions remain callable as safe functions in earlier editions (e.g., 2015, 2018, 2021) to avoid breaking existing codebases [1][2]. In the 2024 Edition, they must be called within an unsafe block [1]. 3. Windows Exception: These functions are considered sound to call in both single-threaded and multithreaded programs on Windows, as the operating system provides thread-safe APIs for environment manipulation [3][4]. 4. Alternatives: The Rust documentation recommends using Command::env and related methods to pass environment variables to child processes instead of modifying the environment of the current process [3][4][5]. For developers migrating to the 2024 Edition, the deprecated_safe_2024 lint can assist by automatically wrapping existing calls in unsafe blocks to maintain compatibility, though developers should audit these calls to ensure they meet safety requirements [1]. Citations:
Avoid mutating the process environment in this test. The test harness can run other tests concurrently in the same process. Those tests can observe 🤖 Prompt for AI AgentsSources: Coding guidelines, MCP tools |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # SPDX-FileCopyrightText: 2026 Sequent Tech Inc <legal@sequentech.io> | ||
| # | ||
| # SPDX-License-Identifier: AGPL-3.0-only | ||
|
|
||
| [package] | ||
| name = "headless-load-test" | ||
| version = "0.1.0" | ||
| edition = "2021" | ||
| default-run = "headless-load-test" | ||
|
|
||
| [dependencies] | ||
| anyhow = { workspace = true } | ||
| clap = { version = "4.5", features = ["derive", "env"] } | ||
| serde = { workspace = true } | ||
| serde_json = { workspace = true } | ||
| serde_yaml = "0.9" | ||
| reqwest = { version = "0.12", features = ["json"] } | ||
| graphql_client = "0.14" | ||
| tokio = { workspace = true } | ||
| uuid = { version = "1.5", features = ["v4", "fast-rng"] } | ||
| sequent-core = { path = "../sequent-core", features = ["default_features"] } | ||
| strand = { path = "../strand" } | ||
| csv = "1.1" | ||
|
|
||
| [[bin]] | ||
| name = "headless-load-test" | ||
| path = "src/main.rs" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Narrow the rationale for this opt-in.
The bundled template configures an
auth_timemapper for password-grant clients inpackages/headless-load-test/src/config/template.rs, Lines 99-134. Therefore, “true for any” password-grant login and “Needed for headless-load-test” are too broad. State that this fallback is only for environments whose tokens still lackauth_time; otherwise the comment may encourage unnecessary weakening of the browser-origin check.As per coding guidelines, remove explanatory boilerplate and keep the configuration comment limited to the maintained contract.
🤖 Prompt for AI Agents
Source: Coding guidelines