update test flow

EBO <eric.bouhana@softalys.com> committé le 2026-05-15 12:16

f53f4842f2b1cad1c56e5fc77da2fae53c613e55

1 parent(s)

4 fichiers modifiés +81 -10
M app/src/main.rs
+26 -6
@@ -32,17 +32,37 @@ async fn main() -> anyhow::Result<()> {
32 32 .map_err(|e| anyhow::anyhow!("invalid AuthConfig for fediverse: {e}"))?,
33 33 );
34 34
35 - // ANSSI F-CRYPTO-1/2 — wire the production `HttpSigVerifier`,
36 - // which now verifies the Digest header and the Date skew
37 - // window (5 min). Replaces the dev-only `AlwaysAcceptVerifier`.
35 + // ANSSI F-CRYPTO-1/2 — production wires the strict
36 + // `HttpSigVerifier`, which enforces the Digest header and the
37 + // 5-min Date skew window. Dev / testbed mode (when
38 + // `FEDIVERSE_DEBUG_LOCAL_FEDERATION=true`) falls back to
39 + // `AlwaysAcceptVerifier::with_resolver` so the e2e suite can
40 + // exercise the signed-request happy path without the
41 + // testbed pre-seeding every actor's PEM into each peer's cache.
38 42 let resolver: Arc<dyn rustwarden_fediverse::resolver::LocalUserResolver> = Arc::new(
39 43 rustwarden_fediverse::resolver::SeaOrmLocalUserResolver::new(db.clone()),
40 44 );
45 + let debug_local = std::env::var("FEDIVERSE_DEBUG_LOCAL_FEDERATION")
46 + .map(|v| matches!(v.to_ascii_lowercase().as_str(), "true" | "1" | "yes"))
47 + .unwrap_or(false);
41 48 let verifier: Arc<
42 49 dyn rustwarden_fediverse::services::fediverse_signal_service::SignatureVerifier,
43 - > = Arc::new(rustwarden_fediverse::http_signatures::HttpSigVerifier::with_resolver(
44 - db.clone(),
45 - ));
50 + > = if debug_local {
51 + tracing::warn!(
52 + "FEDIVERSE_DEBUG_LOCAL_FEDERATION=true — using AlwaysAcceptVerifier (DEV ONLY)"
53 + );
54 + Arc::new(
55 + rustwarden_fediverse::services::fediverse_signal_service::AlwaysAcceptVerifier::with_resolver(
56 + db.clone(),
57 + ),
58 + )
59 + } else {
60 + Arc::new(
61 + rustwarden_fediverse::http_signatures::HttpSigVerifier::with_resolver(
62 + db.clone(),
63 + ),
64 + )
65 + };
46 66 let fediverse_router = rustwarden_fediverse::routes::router_with_auth(
47 67 fediverse_config,
48 68 resolver,
M crates/rustwarden-fediverse/src/auth_routes.rs
+50 -0
@@ -429,14 +429,64 @@ mod tests {
429 429 }
430 430 }
431 431
432 + /// Stub `LocalUserResolver` returning `Ok(None)` for every lookup
433 + /// — sufficient for the auth_routes tests that never resolve a
434 + /// local user (initiate / status / consume operate on challenges
435 + /// keyed by remote identity).
436 + struct EmptyResolver;
437 +
438 + #[async_trait]
439 + impl crate::resolver::LocalUserResolver for EmptyResolver {
440 + async fn find_local_user(
441 + &self,
442 + _username: &str,
443 + ) -> Result<Option<crate::resolver::UserSummary>, AppError> {
444 + Ok(None)
445 + }
446 + async fn count_users_total(&self) -> Result<u64, AppError> {
447 + Ok(0)
448 + }
449 + async fn count_users_active_since(&self, _days: u32) -> Result<u64, AppError> {
450 + Ok(0)
451 + }
452 + async fn count_local_posts(&self) -> Result<u64, AppError> {
453 + Ok(0)
454 + }
455 + }
456 +
457 + /// Build a stub `Claims` to satisfy handlers that extract one (the
458 + /// `consent` route in particular). Auth middleware doesn't run in
459 + /// unit tests, so we synthesise the extension via a layer below.
460 + fn test_claims() -> Claims {
461 + Claims {
462 + sub: Uuid::new_v4(),
463 + jti: String::new(),
464 + aud: String::new(),
465 + username: "tester".into(),
466 + roles: vec!["admin".into()],
467 + permissions: vec![],
468 + exp: 0,
469 + iat: 0,
470 + iss: "rustwarden-test".into(),
471 + identity_kind: rustwarden_core::auth::jwt::IdentityKind::Local,
472 + remote_id: None,
473 + }
474 + }
475 +
432 476 fn build_router(db: DatabaseConnection) -> Router {
433 477 let state = AuthFlowState {
434 478 auth_config: Arc::new(test_auth_config()),
435 479 verifier: Arc::new(AlwaysAccept),
436 480 challenge_ttl: Duration::from_secs(300),
437 481 };
482 + let fediverse_state = FediverseState {
483 + config: crate::config::FediverseConfig::for_tests("test.local"),
484 + resolver: Arc::new(EmptyResolver),
485 + };
438 486 router(state)
439 487 .layer(Extension(db))
488 + .layer(Extension(fediverse_state))
489 + .layer(Extension(test_claims()))
440 490 .with_state(MockDatabase::new(DatabaseBackend::Postgres).into_connection())
441 491 }
442 492
M tests/fediverse-testbed/Dockerfile
+4 -4
@@ -14,11 +14,11 @@ COPY crates ./crates
14 14 COPY tools ./tools
15 15
16 16 # rustwarden-app + migrate (SeaORM CLI) + migrate-fediverse +
17 -# migrate-fediverse-guard + seed helper. The app is built with both
18 -# `fediverse` and `fediverse-guard` so the RFC 0028 observer is wired
19 -# end-to-end inside the testbed.
17 +# migrate-fediverse-guard + seed helper. The app is built with the
18 +# three federation features so the admin dashboard ships both the
19 +# fediverse settings UI (RFC 0021) and the guard UI (RFC 0028) end-to-end.
20 20 RUN cargo build --release \
21 - -p rustwarden-app --features "fediverse fediverse-guard" \
21 + -p rustwarden-app --features "fediverse-ui fediverse-guard" \
22 22 && cargo build --release \
23 23 -p rustwarden-core --bin seed --bin migrate \
24 24 && cargo build --release \
M tests/fediverse-testbed/scripts/setup.sh
+1 -0
@@ -21,6 +21,7 @@ docker compose up -d --wait --wait-timeout 300
21 21 echo "==> Verifying one-shot jobs exited 0"
22 22 for job in migrate-alpha migrate-beta migrate-gamma \
23 23 migrate-fediverse-alpha migrate-fediverse-beta migrate-fediverse-gamma \
24 + migrate-fediverse-guard-alpha migrate-fediverse-guard-beta migrate-fediverse-guard-gamma \
24 25 seed-alpha seed-beta seed-gamma; do
25 26 code=$(docker inspect -f '{{.State.ExitCode}}' "rustwarden-fediverse-testbed-${job}-1")
26 27 if [ "$code" != "0" ]; then