fix: retain Session recovery failures across real trust rejection

This commit is contained in:
2026-11-04 20:39:16 +09:00
parent 9fadd1bcaf
commit 6c67390567
4 changed files with 45 additions and 12 deletions
Generated
+1
View File
@@ -7580,6 +7580,7 @@ dependencies = [
"content-history",
"content-history-adapters",
"content-history-store",
"error-contract",
"feature-storage",
"flate2",
"flow",
@@ -116,7 +116,7 @@ impl ProfileRuntimeWorkerFactory {
.await;
let mut worker = worker_result.map_err(|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 sessions = worker.workdir_sessions();
@@ -141,11 +141,13 @@ impl ProfileRuntimeWorkerFactory {
.map_err(|_| cause("recovery Backend Job binding failed"))?;
}
worker
.finalize_subjektiv_session_attribution(
.finalize_subjektiv_session_attribution_retaining_startup_failure(
request.request.subjektiv_attached,
SubjektivSessionAttributionLifecycle::RestoredSession,
)
.map_err(|error| cause(restore_worker_cause(&error)))?;
.map_err(|error| {
RuntimeRestoreFailure::from_worker(RuntimeRestoreStage::Recovery, error)
})?;
if pending {
worker::WorkerController::recover_pending_head(&mut worker, &root)
.await
@@ -161,21 +163,38 @@ impl ProfileRuntimeWorkerFactory {
tasks
.shutdown()
.await
.map_err(|_| cause("recovery Feature settlement failed"))?;
.map_err(|_| RuntimeRestoreCleanupFailure::Feature)?;
sessions
.close_all()
.await
.map_err(|_| cause("recovery Workdir close failed"))?;
.map_err(|_| RuntimeRestoreCleanupFailure::Workdir)?;
if let Some(allocation) = allocation {
allocation
.release()
.map_err(|_| cause("recovery allocation release failed"))?;
.map_err(|_| RuntimeRestoreCleanupFailure::Allocation)?;
}
Ok::<_, RuntimeRestoreFailure>(())
Ok::<_, RuntimeRestoreCleanupFailure>(())
}
.await;
result?;
cleanup?;
match (result, 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
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
+1
View File
@@ -66,6 +66,7 @@ webauthn-rs = { workspace = true, features = ["conditional-ui"] }
webauthn-rs-proto = "0.5.5"
[dev-dependencies]
error-contract.workspace = true
content-history.workspace = true
content-history-store.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.publications.load(SeqCst), 0);
assert_eq!(fixture.model.calls.load(SeqCst), model_before);
assert!(
matches!(metadata.read_by_name(&name).unwrap().unwrap().subjektiv_session_attribution,
Some(session_store::SubjektivSessionAttributionState::Failed { session_id: id, .. }) if id == session_id)
let saved_failure = metadata.read_by_name(&name).unwrap().unwrap();
// Trust rejection occurs before the Session domain handler. An unsigned
// 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();
assert_eq!(