A run says whether the dashboard, the CLI or a script asked for it

`POST /runs/flows/{name}` hardcoded `cause: "api"`, so every row in the
history claimed the same origin. The body now carries an optional `cause`,
closed to the values the column knows — the dashboard sends nothing and stays
"api", `fluksio run` says "cli", and the SDK client says "sdk".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Gf7WaExcJ9bs3kfJXB3nK
This commit is contained in:
2026-08-25 22:06:29 +02:00
co-authored by Claude Opus 5
parent b194071ca5
commit 1148e54c9e
9 changed files with 83 additions and 9 deletions
+38
View File
@@ -311,6 +311,44 @@ def test_a_running_run_reports_how_long_it_has_been_going(
assert rows[0]["duration_ms"] >= 30_000
def test_a_run_records_which_caller_asked_for_it(
client, superuser_token_headers, monkeypatch
):
"""The dashboard, the CLI and the SDK are told apart by what they send.
Client-supplied, so the vocabulary is closed: a column nobody can write
free text into is one a table can group by.
"""
seen: dict[str, object] = {}
class Recorder:
def submit(self, name, **kwargs):
seen.update(kwargs)
return Run(
id="cause-1",
flow=name,
cause=str(kwargs["cause"]),
created_at=datetime.now(UTC),
)
monkeypatch.setattr(client.app.state, "run_service", Recorder())
url = f"{settings.API_V1_STR}/runs/flows/demo"
answer = client.post(url, headers=superuser_token_headers, json={"cause": "cli"})
assert answer.status_code == 202
assert (seen["cause"], answer.json()["cause"]) == ("cli", "cli")
# Nothing said still means the dashboard, which is the only caller that
# does not name itself.
client.post(url, headers=superuser_token_headers, json={})
assert seen["cause"] == "api"
refused = client.post(
url, headers=superuser_token_headers, json={"cause": "somewhere else"}
)
assert refused.status_code == 422
def test_overview_is_not_read_as_a_run_id(client, superuser_token_headers):
"""`/overview` is declared before `/{run_id}`, which would swallow it."""
answer = client.get(