fix: adapt T-769 recovery onto current restore lane checkpoint

UNCOMPILED TRANSPORT / PRESERVATION CHECKPOINT, NOT A VALIDATED CANDIDATE. One-time recovery authorization permits publication before validation so the parent can validate this exact source in a separate Workdir. Prior compilation attempts were interrupted by Workdir-session unavailability; cause and test outcome remain unknown. No Cargo build/check/test was started in this bounded checkpoint turn.

Merge current lane 4ef7b03651 into existing source b7a22146a0. Selectively adapt typed factory failure and same-operation cleanup/replay while preserving current saved Feature restore and operation-time authorization, logical/deferred Workdirs, T765 Host/schema and T768 replay-safe Subject grant. No T770/T771 implementation.

All 19 target-relative paths and added test bodies were source-audited. Workspace fmt check, scoped rustfmt, whitespace/diff checks passed; conflict markers zero. Excluded unrelated formatter changes and untracked compiler artifacts. Local audit: target/t769-checkpoint/AUDIT.md.

Handoff to parent: compile and run focused and package/API regressions on this exact source, fix as necessary, then obtain fresh independent review. Existing MR 01a15606-a6ba-7d23-8d60-0874607399e7 only; no new review requested here. No acceptance, approval, adoption, target/develop push, integration, Ticket closure or service update is asserted.
This commit is contained in:
2026-10-21 00:20:54 +09:00
238 changed files with 29879 additions and 5011 deletions
+57 -58
View File
@@ -225,8 +225,14 @@ impl WorkspaceClient for AvailableWorkspaceClient {
fn execute(
&self,
_request: WorkspaceRequest,
request: WorkspaceRequest,
) -> Result<WorkspaceResponse, WorkspaceClientError> {
if request.path.ends_with("/authorization/check") {
return Ok(WorkspaceResponse {
status: 200,
body: "{}".into(),
});
}
Err(WorkspaceClientError::Unavailable("test".to_string()))
}
}
@@ -249,8 +255,14 @@ impl WorkspaceClient for NoopWorkspaceClient {
fn execute(
&self,
_request: WorkspaceRequest,
request: WorkspaceRequest,
) -> Result<WorkspaceResponse, WorkspaceClientError> {
if request.path.ends_with("/authorization/check") {
return Ok(WorkspaceResponse {
status: 200,
body: "{}".into(),
});
}
Err(WorkspaceClientError::Unavailable(
"test client does not execute requests".to_string(),
))
@@ -311,8 +323,7 @@ async fn spawn_controller(worker: Worker<MockClient, TestStore>) -> WorkerHandle
let tmp = tempfile::tempdir().unwrap();
let runtime_base = tmp.path().to_owned();
std::mem::forget(tmp);
let bash_output_dir = runtime_base.join("bash-output");
let (handle, _shutdown_rx) = WorkerController::spawn(worker, &runtime_base, &bash_output_dir)
let (handle, _shutdown_rx) = WorkerController::spawn(worker, &runtime_base)
.await
.unwrap();
handle
@@ -342,13 +353,9 @@ async fn canonical_worker_handle_uploads_and_submits_attachment() {
)
.await
.unwrap();
let (handle, shutdown_rx) = WorkerController::spawn(
worker,
&root.path().join("runtime"),
&root.path().join("bash-output"),
)
.await
.unwrap();
let (handle, shutdown_rx) = WorkerController::spawn(worker, &root.path().join("runtime"))
.await
.unwrap();
let mut rx = handle.subscribe();
let file = handle
.upload_file_with_context(
@@ -408,24 +415,20 @@ async fn canonical_worker_handle_uploads_and_submits_attachment() {
}
#[tokio::test]
async fn controller_grants_read_scope_for_exact_bash_output_directory() {
async fn controller_does_not_grant_or_create_a_model_visible_bash_output_directory() {
let worker = make_worker(MockClient::new(simple_text_events())).await;
let shared_scope = worker.scope().clone();
let runtime_base = tempfile::tempdir().unwrap();
let worker_tmp = tempfile::tempdir().unwrap();
let bash_output_dir = worker_tmp.path().join("worker-1").join("bash-output");
let original_rules = shared_scope.snapshot().allow_rules().to_vec();
let (handle, shutdown_rx) =
WorkerController::spawn(worker, runtime_base.path(), &bash_output_dir)
.await
.unwrap();
let (handle, shutdown_rx) = WorkerController::spawn(worker, runtime_base.path())
.await
.unwrap();
assert!(bash_output_dir.is_dir());
assert!(shared_scope.snapshot().allow_rules().iter().any(|rule| {
rule.target == bash_output_dir
&& rule.permission == manifest::Permission::Read
&& rule.recursive
}));
assert_eq!(
shared_scope.snapshot().allow_rules(),
original_rules.as_slice()
);
assert!(!handle.runtime_dir.path().join("bash-output").exists());
handle
@@ -451,9 +454,9 @@ async fn shutdown_closes_bound_workdir_session() {
.start_command(CommandRequest {
command: "sleep 30".to_owned(),
timeout_secs: 60,
output_limit: 1024,
transport_byte_budget: workdir::MAX_COMMAND_TRANSPORT_BYTES,
cwd: workdir::WorkdirPath::root(),
spill_dir: None,
tool_call_id: None,
})
.await
@@ -461,11 +464,9 @@ async fn shutdown_closes_bound_workdir_session() {
worker.bind_single_workdir_session(Some(Arc::clone(&session)));
let runtime_base = tempfile::tempdir().unwrap();
let bash_output_dir = runtime_base.path().join("bash-output");
let (handle, shutdown_rx) =
WorkerController::spawn(worker, runtime_base.path(), &bash_output_dir)
.await
.unwrap();
let (handle, shutdown_rx) = WorkerController::spawn(worker, runtime_base.path())
.await
.unwrap();
handle
.send(Method::Shutdown {
command: worker_command(&handle),
@@ -501,9 +502,9 @@ async fn controller_filters_workdir_command_not_owned_by_worker() {
.start_command(CommandRequest {
command: "sleep 0.2".to_owned(),
timeout_secs: 5,
output_limit: 1024,
transport_byte_budget: workdir::MAX_COMMAND_TRANSPORT_BYTES,
cwd: workdir::WorkdirPath::root(),
spill_dir: None,
tool_call_id: Some("foreign-tool-call".into()),
})
.await
@@ -529,7 +530,10 @@ async fn controller_filters_workdir_command_not_owned_by_worker() {
})
.await
.unwrap();
assert_eq!(output.status, workdir::CommandStatus::Completed);
assert_eq!(
output.terminal.unwrap().status,
workdir::CommandStatus::Completed
);
handle
.send(Method::Shutdown {
command: worker_command(&handle),
@@ -738,9 +742,8 @@ async fn controller_startup_failure_closes_bound_workdir_session() {
let invalid_runtime_base = runtime_base.path().join("not-a-directory");
std::fs::write(&invalid_runtime_base, "file").unwrap();
let bash_output_dir = runtime_base.path().join("bash-output");
assert!(
WorkerController::spawn(worker, &invalid_runtime_base, &bash_output_dir)
WorkerController::spawn(worker, &invalid_runtime_base)
.await
.is_err()
);
@@ -749,9 +752,9 @@ async fn controller_startup_failure_closes_bound_workdir_session() {
.start_command(CommandRequest {
command: "printf unreachable".to_owned(),
timeout_secs: 5,
output_limit: 1024,
transport_byte_budget: workdir::MAX_COMMAND_TRANSPORT_BYTES,
cwd: workdir::WorkdirPath::root(),
spill_dir: None,
tool_call_id: None,
})
.await,
@@ -926,11 +929,7 @@ mod socket_startup_failure {
let result = tokio::time::timeout(
std::time::Duration::from_secs(5),
WorkerController::spawn_runtime_managed_run(
worker,
&run_dir,
&root.path().join("bash-output"),
),
WorkerController::spawn_runtime_managed_run(worker, &run_dir),
)
.await
.expect("socket startup and rollback must settle");
@@ -953,9 +952,8 @@ mod socket_startup_failure {
.start_command(CommandRequest {
command: "printf unreachable".to_owned(),
timeout_secs: 5,
output_limit: 1024,
transport_byte_budget: workdir::MAX_COMMAND_TRANSPORT_BYTES,
cwd: workdir::WorkdirPath::root(),
spill_dir: None,
tool_call_id: None,
})
.await,
@@ -1117,6 +1115,12 @@ impl WorkspaceClient for JournalWorkspaceClient {
&self,
request: WorkspaceRequest,
) -> Result<WorkspaceResponse, WorkspaceClientError> {
if request.path.ends_with("/authorization/check") {
return Ok(WorkspaceResponse {
status: 200,
body: "{}".into(),
});
}
self.requests.lock().unwrap().push(request.clone());
let (status, body) = if request.path.ends_with("/subjektiv/journal/job/finish") {
(
@@ -1758,8 +1762,7 @@ permission = "write"
let client = MockClient::new(simple_text_events());
let worker = make_worker_with_pwd_and_manifest(client, manifest).await.0;
let tmp = tempfile::tempdir().unwrap();
let bash_output_dir = tmp.path().join("bash-output");
let result = WorkerController::spawn(worker, tmp.path(), &bash_output_dir).await;
let result = WorkerController::spawn(worker, tmp.path()).await;
assert!(
result.is_ok(),
"feature exposure must not imply delegation authority"
@@ -3132,11 +3135,9 @@ async fn status_json_reflects_worker_name() {
async fn shutdown_closes_method_admission_before_terminal_confirmation() {
let worker = make_worker(MockClient::new(simple_text_events())).await;
let runtime_base = tempfile::tempdir().unwrap();
let bash_output_dir = runtime_base.path().join("bash-output");
let (handle, mut shutdown_rx) =
WorkerController::spawn(worker, runtime_base.path(), &bash_output_dir)
.await
.unwrap();
let (handle, mut shutdown_rx) = WorkerController::spawn(worker, runtime_base.path())
.await
.unwrap();
handle
.send(Method::Shutdown {
command: worker_command(&handle),
@@ -3171,11 +3172,9 @@ async fn shutdown_joins_socket_server_with_active_connection() {
let worker = make_worker(MockClient::new(simple_text_events())).await;
let runtime_base = tempfile::tempdir().unwrap();
let bash_output_dir = runtime_base.path().join("bash-output");
let (handle, shutdown_rx) =
WorkerController::spawn(worker, runtime_base.path(), &bash_output_dir)
.await
.unwrap();
let (handle, shutdown_rx) = WorkerController::spawn(worker, runtime_base.path())
.await
.unwrap();
let socket_path = handle.runtime_dir.socket_path();
let _connection = UnixStream::connect(&socket_path).await.unwrap();
@@ -3292,7 +3291,7 @@ async fn socket_worker_event_turn_ended_while_idle_auto_starts_turn() {
Ok(Some(Event::SystemItem { ref item, .. }))
if item.get("kind").and_then(|k| k.as_str()) == Some("worker_event")
&& item
.pointer("/event/worker_name")
.pointer("/presentation/event/worker_name")
.and_then(|v| v.as_str()) == Some("child") =>
{
saw_worker_event_echo = true;