From 7df52fb20ec010adc459e72d12a900ac02bf88e2 Mon Sep 17 00:00:00 2001 From: Anubhav-Rai Date: Thu, 29 Oct 2026 10:09:15 +0530 Subject: [PATCH] automation: a proxy's relative name is a template, not a path (#2479) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Asked for on the PR: #1347 allows `file.createProxy` a name that is not a path, because the engine reads it as an Output Module template, and the `WRITES` entry added here refused exactly that. Dropped, so the classification is #1347's alone. Nothing is opened by it. A proxy named outside the roots is still refused — `cannot read` now rather than `cannot write`, which is #1347's to settle — so the test asserts the refusal and no longer its wording. A relative name is now accepted and resolves beside the saved project, inside the write root, which the test pins so this does not quietly come back. The lookup this PR is for is untouched: `file.createProxy` stays in `QUEUES_AN_OUTPUT`, so a proxy queued from a project with no file is still refused rather than landing in the home folder. Co-Authored-By: Claude Opus 5 --- crates/automation/src/confine.rs | 1 - crates/automation/src/tests.rs | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/automation/src/confine.rs b/crates/automation/src/confine.rs index ce6717f30..3a4d462e4 100644 --- a/crates/automation/src/confine.rs +++ b/crates/automation/src/confine.rs @@ -86,7 +86,6 @@ const WRITES: &[(&str, &[&str])] = &[ ("essential.exportTemplate", &["path"]), ("shortcuts.export", &["path"]), ("renderQueue.add", &["output", "path"]), - ("file.createProxy", &["path", "output"]), ]; /// Commands that write where they are not told: the project's file, the Render Queue's outputs. diff --git a/crates/automation/src/tests.rs b/crates/automation/src/tests.rs index 61a726d6b..088bca335 100644 --- a/crates/automation/src/tests.rs +++ b/crates/automation/src/tests.rs @@ -1414,12 +1414,16 @@ fn automation_roots_refuse_a_queued_output_from_an_unsaved_project() { assert_eq!(queue["items"].as_array().map(Vec::len), Some(0), "nothing was queued: {queue}"); // Naming an output inside a write root is how it is done. call_json(&mut s, "execute_command", json!({"command": "renderQueue.add", "params": {"comp": "A", "output": p("named.mp4")}})); - // A proxy's own `path` is a write, not the read it used to be checked as (#2131 F-11). + // A proxy named outside the roots is refused. Whether that reads as a write or a read is + // #1347's to classify, so this asserts the refusal and not its wording. let (c, err) = call(&mut s, "execute_command", json!({"command": "file.createProxy", "params": {"comp": "A", "path": "/elsewhere/proxy.mov"}})); assert!(err, "a proxy outside the roots should be refused: {c:?}"); - assert!(c[0]["text"].as_str().unwrap_or_default().contains("cannot write"), "{c:?}"); + assert!(c[0]["text"].as_str().unwrap_or_default().contains("outside the automation roots"), "{c:?}"); // Once the project is saved there, the default output (beside it) is queued as before. call_json(&mut s, "save_project", json!({"path": p("proj.ecproj")})); + // A name that is not a path is an Output Module template, and the output it resolves to lands + // beside the saved project: inside the write root, so it is allowed (#1347 relies on this). + call_json(&mut s, "execute_command", json!({"command": "file.createProxy", "params": {"comp": "A", "path": "ProxyTemplate"}})); call_json(&mut s, "execute_command", json!({"command": "renderQueue.add", "params": {"comp": "A"}})); let queue = call_json(&mut s, "execute_command", json!({"command": "renderQueue.list"})); let out = queue["items"][1]["outputPath"].as_str().unwrap_or_default();