fix(workflows): reject mismatched run state IDs (#3899)

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Marsel Safin
2026-08-03 14:30:55 -05:00
committed by GitHub
co-authored by Copilot
parent 58f5d6e258
commit cda7a921a4
2 changed files with 34 additions and 0 deletions
+5
View File
@@ -761,6 +761,11 @@ class RunState:
"Invalid run state: missing required field(s): "
+ ", ".join(missing_fields)
)
if state_data["run_id"] != run_id:
raise ValueError(
f"Invalid run state: stored run_id {state_data['run_id']!r} "
f"does not match requested run_id {run_id!r}"
)
workflow_id = state_data["workflow_id"]
if not isinstance(workflow_id, str) or not _ID_PATTERN.fullmatch(
+29
View File
@@ -7053,6 +7053,35 @@ class TestRunState:
with pytest.raises(FileNotFoundError):
RunState.load("nonexistent", project_dir)
def test_load_rejects_stored_run_id_mismatch(self, project_dir):
"""The state payload cannot redirect later writes to another run."""
from specify_cli.workflows.engine import RunState
run_dir = (
project_dir
/ ".specify"
/ "workflows"
/ "runs"
/ "requested-run"
)
run_dir.mkdir(parents=True)
(run_dir / "state.json").write_text(
json.dumps(
{
"run_id": "other-run",
"workflow_id": "test-workflow",
"status": "created",
}
),
encoding="utf-8",
)
with pytest.raises(
ValueError,
match="stored run_id 'other-run' does not match requested run_id 'requested-run'",
):
RunState.load("requested-run", project_dir)
@pytest.mark.parametrize(
("installed_workflow_id", "installed_registry_root"),
[