fix(m7): red write always lands on executed + state pill out of Commentaires
User reported two issues on the scenario table:
1. After filling only red_command + executed_at, the pill read
"Reviewed" instead of "Awaiting review". Cause: the auto-promotion
was gated on `state in {pending, skipped, blocked}`, so a test that
blue had already reviewed stayed in `reviewed_by_blue` after a red
edit. That contradicts the implicit lifecycle (red modifying a
reviewed test invalidates the review).
2. The state pill lived inside the Commentaires column, polluting a
cell meant for blue-team comments.
Fixes
- backend/app/services/mission_tests.py: any red-side write now lands
the state on `executed` unconditionally (including from
`reviewed_by_blue`). Same-PUT red+blue still flows
executed → reviewed_by_blue.
- frontend/src/pages/MissionScenarioTable.tsx: state pill moves from
CommentairesCell to the Test column (top of the row, above the
snapshot name + MITRE chips). Commentaires now holds only the
detection_level pill + blue_comment_md.
Tests
- New pytest: `test_red_write_on_reviewed_reverts_to_executed` —
reviewed_by_blue + red edit ⇒ executed. 143 pytest green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -644,6 +644,41 @@ def test_red_writing_any_red_field_implicitly_executes_and_stamps(
|
||||
assert body["executed_at_overridden"] is False
|
||||
|
||||
|
||||
def test_red_write_on_reviewed_reverts_to_executed(
|
||||
client, admin_token, catalogue, red_user, blue_user
|
||||
):
|
||||
"""When red modifies a test that blue had already reviewed, the state
|
||||
reverts to `executed` (awaiting re-review). The red edits invalidate
|
||||
the previous review — user feedback 2026-05-15 ter."""
|
||||
mission = _make_mission(
|
||||
client, admin_token, name="m7-red-after-review",
|
||||
scenario_id=catalogue["scenario"]["id"],
|
||||
red_id=red_user["id"], blue_id=blue_user["id"],
|
||||
)
|
||||
tid = _first_test_id(mission)
|
||||
# Red executes.
|
||||
client.put(
|
||||
f"/api/v1/missions/{mission['id']}/tests/{tid}",
|
||||
headers=_bearer(red_user["token"]),
|
||||
json={"red_command": "first attempt"},
|
||||
)
|
||||
# Blue reviews — state becomes reviewed_by_blue.
|
||||
blue_done = client.put(
|
||||
f"/api/v1/missions/{mission['id']}/tests/{tid}",
|
||||
headers=_bearer(blue_user["token"]),
|
||||
json={"blue_comment_md": "alert raised"},
|
||||
)
|
||||
assert blue_done.get_json()["state"] == "reviewed_by_blue"
|
||||
# Red modifies their command — state should drop back to executed.
|
||||
re_red = client.put(
|
||||
f"/api/v1/missions/{mission['id']}/tests/{tid}",
|
||||
headers=_bearer(red_user["token"]),
|
||||
json={"red_command": "second attempt"},
|
||||
)
|
||||
assert re_red.status_code == 200
|
||||
assert re_red.get_json()["state"] == "executed"
|
||||
|
||||
|
||||
def test_blue_writing_any_blue_field_promotes_executed_to_reviewed(
|
||||
client, admin_token, catalogue, red_user, blue_user
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user