STATE-WP-0069 T04: meter workstream_id query-param aliases
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s

Add legacy_compat helper and Deprecation headers when callers filter
/tasks, /decisions, /token-events, or /execution/launch-requests with
workstream_id. Preferred workplan_id filters are unchanged. Route removal
remains gated on legacy-meter zero-usage windows.
This commit is contained in:
tegwick 2026-07-08 21:32:14 +02:00
parent b2b72b7327
commit 793a39a1a4
8 changed files with 181 additions and 15 deletions

View file

@ -143,6 +143,46 @@ class TestWorkplanAliasesAndLegacyMeter:
assert event["interface"]["replacement_ref"] == "org.statehub.workplan.completed"
assert event["window"]["components"] == {"state-hub.events": 1}
async def test_legacy_workstream_id_query_param_on_tasks_is_metered(self, client):
await _create_domain(client)
topic = await _create_topic(client)
wp = await _create_workplan(client, topic["id"])
task_r = await client.post("/tasks/", json={
"workplan_id": wp["id"],
"title": "Meter me",
"status": "todo",
})
assert task_r.status_code == 201, task_r.text
r = await client.get(
f"/tasks/?workstream_id={wp['id']}",
headers={
"X-StateHub-Tenant": "tenant-a",
"X-StateHub-User": "alice",
"X-StateHub-Component": "old-task-client",
},
)
assert r.status_code == 200
assert r.headers["Deprecation"] == "true"
assert r.headers["X-StateHub-Replacement"] == "/tasks/?workplan_id=<workplan_id>"
summary = (await client.get("/legacy-meter/summary")).json()
item = _summary_by_key(summary)["rest_api:GET /tasks/?workstream_id"]
assert item["window"]["calls"] == 1
assert item["window"]["components"] == {"old-task-client": 1}
async def test_workplan_id_query_param_on_tasks_is_not_metered(self, client):
await _create_domain(client)
topic = await _create_topic(client)
wp = await _create_workplan(client, topic["id"])
r = await client.get(f"/tasks/?workplan_id={wp['id']}")
assert r.status_code == 200
assert r.headers.get("Deprecation") != "true"
summary = (await client.get("/legacy-meter/summary")).json()
assert _summary_by_key(summary).get("rest_api:GET /tasks/?workstream_id") is None
async def test_workplan_dependency_and_execution_aliases(self, client):
await _create_domain(client)
topic = await _create_topic(client)