fix: retain Session recovery failures across real trust rejection
This commit is contained in:
Generated
+1
@@ -7580,6 +7580,7 @@ dependencies = [
|
|||||||
"content-history",
|
"content-history",
|
||||||
"content-history-adapters",
|
"content-history-adapters",
|
||||||
"content-history-store",
|
"content-history-store",
|
||||||
|
"error-contract",
|
||||||
"feature-storage",
|
"feature-storage",
|
||||||
"flate2",
|
"flate2",
|
||||||
"flow",
|
"flow",
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ impl ProfileRuntimeWorkerFactory {
|
|||||||
.await;
|
.await;
|
||||||
let mut worker = worker_result.map_err(|error| {
|
let mut worker = worker_result.map_err(|error| {
|
||||||
self.retain_construction_failure(request, &error);
|
self.retain_construction_failure(request, &error);
|
||||||
cause(restore_worker_cause(&error))
|
RuntimeRestoreFailure::from_worker(RuntimeRestoreStage::Recovery, error)
|
||||||
})?;
|
})?;
|
||||||
let tasks = worker.retain_startup_feature_cleanup();
|
let tasks = worker.retain_startup_feature_cleanup();
|
||||||
let sessions = worker.workdir_sessions();
|
let sessions = worker.workdir_sessions();
|
||||||
@@ -141,11 +141,13 @@ impl ProfileRuntimeWorkerFactory {
|
|||||||
.map_err(|_| cause("recovery Backend Job binding failed"))?;
|
.map_err(|_| cause("recovery Backend Job binding failed"))?;
|
||||||
}
|
}
|
||||||
worker
|
worker
|
||||||
.finalize_subjektiv_session_attribution(
|
.finalize_subjektiv_session_attribution_retaining_startup_failure(
|
||||||
request.request.subjektiv_attached,
|
request.request.subjektiv_attached,
|
||||||
SubjektivSessionAttributionLifecycle::RestoredSession,
|
SubjektivSessionAttributionLifecycle::RestoredSession,
|
||||||
)
|
)
|
||||||
.map_err(|error| cause(restore_worker_cause(&error)))?;
|
.map_err(|error| {
|
||||||
|
RuntimeRestoreFailure::from_worker(RuntimeRestoreStage::Recovery, error)
|
||||||
|
})?;
|
||||||
if pending {
|
if pending {
|
||||||
worker::WorkerController::recover_pending_head(&mut worker, &root)
|
worker::WorkerController::recover_pending_head(&mut worker, &root)
|
||||||
.await
|
.await
|
||||||
@@ -161,21 +163,38 @@ impl ProfileRuntimeWorkerFactory {
|
|||||||
tasks
|
tasks
|
||||||
.shutdown()
|
.shutdown()
|
||||||
.await
|
.await
|
||||||
.map_err(|_| cause("recovery Feature settlement failed"))?;
|
.map_err(|_| RuntimeRestoreCleanupFailure::Feature)?;
|
||||||
sessions
|
sessions
|
||||||
.close_all()
|
.close_all()
|
||||||
.await
|
.await
|
||||||
.map_err(|_| cause("recovery Workdir close failed"))?;
|
.map_err(|_| RuntimeRestoreCleanupFailure::Workdir)?;
|
||||||
if let Some(allocation) = allocation {
|
if let Some(allocation) = allocation {
|
||||||
allocation
|
allocation
|
||||||
.release()
|
.release()
|
||||||
.map_err(|_| cause("recovery allocation release failed"))?;
|
.map_err(|_| RuntimeRestoreCleanupFailure::Allocation)?;
|
||||||
}
|
}
|
||||||
Ok::<_, RuntimeRestoreFailure>(())
|
Ok::<_, RuntimeRestoreCleanupFailure>(())
|
||||||
}
|
}
|
||||||
.await;
|
.await;
|
||||||
result?;
|
match (result, cleanup) {
|
||||||
cleanup?;
|
(Err(mut primary), cleanup) => {
|
||||||
|
primary.cleanup = match cleanup {
|
||||||
|
Ok(()) => RuntimeRestoreCleanup::Confirmed,
|
||||||
|
Err(failure) => {
|
||||||
|
primary.cleanup_failure = Some(failure);
|
||||||
|
RuntimeRestoreCleanup::Failed(failure)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Err(primary);
|
||||||
|
}
|
||||||
|
(Ok(()), Err(cleanup)) => {
|
||||||
|
let mut failure = cause("restore recovery cleanup failed");
|
||||||
|
failure.cleanup_failure = Some(cleanup);
|
||||||
|
failure.cleanup = RuntimeRestoreCleanup::Failed(cleanup);
|
||||||
|
return Err(failure);
|
||||||
|
}
|
||||||
|
(Ok(()), Ok(())) => {}
|
||||||
|
}
|
||||||
self.failed_restore_resources
|
self.failed_restore_resources
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ webauthn-rs = { workspace = true, features = ["conditional-ui"] }
|
|||||||
webauthn-rs-proto = "0.5.5"
|
webauthn-rs-proto = "0.5.5"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
error-contract.workspace = true
|
||||||
content-history.workspace = true
|
content-history.workspace = true
|
||||||
content-history-store.workspace = true
|
content-history-store.workspace = true
|
||||||
content-history-adapters.workspace = true
|
content-history-adapters.workspace = true
|
||||||
|
|||||||
@@ -2365,9 +2365,21 @@ async fn connected_explicit_repair(scenario: ConnectedRepair) {
|
|||||||
assert_eq!(probe.activations.load(SeqCst), 0);
|
assert_eq!(probe.activations.load(SeqCst), 0);
|
||||||
assert_eq!(probe.publications.load(SeqCst), 0);
|
assert_eq!(probe.publications.load(SeqCst), 0);
|
||||||
assert_eq!(fixture.model.calls.load(SeqCst), model_before);
|
assert_eq!(fixture.model.calls.load(SeqCst), model_before);
|
||||||
assert!(
|
let saved_failure = metadata.read_by_name(&name).unwrap().unwrap();
|
||||||
matches!(metadata.read_by_name(&name).unwrap().unwrap().subjektiv_session_attribution,
|
// Trust rejection occurs before the Session domain handler. An unsigned
|
||||||
Some(session_store::SubjektivSessionAttributionState::Failed { session_id: id, .. }) if id == session_id)
|
// legacy 401 attests neither a Session refusal nor absence of earlier effects.
|
||||||
|
assert!(matches!(saved_failure.subjektiv_session_attribution,
|
||||||
|
Some(session_store::SubjektivSessionAttributionState::OutcomeUnknown { session_id: id, .. }) if id == session_id));
|
||||||
|
let session_store::worker_metadata::StartupFailureRead::Present(
|
||||||
|
error_contract::DecodeFailure::Known(cause),
|
||||||
|
) = saved_failure
|
||||||
|
.decode_startup_failure::<protocol::session_failure::SessionRegistrationCause>()
|
||||||
|
else {
|
||||||
|
panic!("recovery must retain its typed Session unknown cause")
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
*cause.facts().cause(),
|
||||||
|
protocol::session_failure::SessionRegistrationCause::outcome_unknown()
|
||||||
);
|
);
|
||||||
let denied = record();
|
let denied = record();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
Reference in New Issue
Block a user