You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@security.apache.org by pk...@apache.org on 2026/09/29 14:20:12 UTC
(security-dash) branch frontend updated: feat(triage): enable for all pmcs (#33)
This is an automated email from the ASF dual-hosted git repository.
ppkarwasz pushed a commit to branch frontend
in repository https://gitbox.apache.org/repos/asf/security-dash.git
The following commit(s) were added to refs/heads/frontend by this push:
new 362e862 feat(triage): enable for all pmcs (#33)
362e862 is described below
commit 362e862e4afaa8f65d4191d9a969a4cb83780dfc
Author: Arnout Engelen <ar...@bzzt.net>
AuthorDate: Tue Sep 29 16:20:08 2026 +0200
feat(triage): enable for all pmcs (#33)
---
app/config.py | 7 -------
app/test_project_view.py | 36 ------------------------------------
app/test_triage.py | 20 +-------------------
app/triage.py | 17 +----------------
config.yaml.example | 4 ----
5 files changed, 2 insertions(+), 82 deletions(-)
diff --git a/app/config.py b/app/config.py
index 53d76b4..2134be1 100644
--- a/app/config.py
+++ b/app/config.py
@@ -53,13 +53,6 @@ class AppConfig(pydantic.BaseModel):
pmcs_with_subprojects: list[str] = []
"""PMCs whose reports are split across subprojects."""
- pmcs_with_triage: list[str] = []
- """PMCs that take their triage decisions through this dashboard.
-
- A decision emails the reporter, so triage is off until a PMC asks for it:
- without its id here, the project view shows no triage form and the triage
- endpoint refuses the project."""
-
pmcs_in_attic: list[str] = []
"""PMCs retired to the Attic, whose reports the security team handles directly"""
diff --git a/app/test_project_view.py b/app/test_project_view.py
index 0696466..dce0e08 100644
--- a/app/test_project_view.py
+++ b/app/test_project_view.py
@@ -40,8 +40,6 @@ _CONFIG = """\
data_dir: {data_dir}
state_dir: {state_dir}
old_cve_close_dates: {{}}
-pmcs_with_triage:
- - cassandra
"""
@@ -74,13 +72,6 @@ def quart_app(tmp_path, monkeypatch):
return _build_app(tmp_path, monkeypatch)
-@pytest.fixture
-def quart_app_without_triage(tmp_path, monkeypatch):
- """A project that has not asked to take its decisions here."""
- config = _CONFIG.replace("pmcs_with_triage:\n - cassandra\n", "")
- return _build_app(tmp_path, monkeypatch, config=config)
-
-
def _login(monkeypatch, uid="jdoe", fullname="J. Doe", committees=("cassandra",), projects=()):
async def read(*args, **kwargs):
return types.SimpleNamespace(
@@ -134,33 +125,6 @@ async def test_untriaged_report_gets_a_triage_form(quart_app, monkeypatch):
assert body.count('type="submit"') == 1
-@sync
-async def test_a_project_without_triage_gets_no_form(quart_app_without_triage, monkeypatch):
- _login(monkeypatch)
- response = await quart_app_without_triage.test_client().get("/project/cassandra")
- body = await response.get_data(as_text=True)
-
- assert response.status_code == 200
- assert "a flaw" in body
- assert "/api/project/cassandra/triage" not in body
- assert '<td class="reports-triage">' not in body
-
-
-@sync
-async def test_a_project_without_triage_refuses_a_decision(
- quart_app_without_triage, monkeypatch, notification_api
-):
- """The opt-in gates the endpoint too, not just the form."""
- _login(monkeypatch)
- response = await quart_app_without_triage.test_client().post(
- "/api/project/cassandra/triage",
- json={"message_id": MESSAGE_ID, "action": "accept"},
- )
-
- assert response.status_code == 404
- assert notification_api.decisions == []
-
-
@sync
async def test_triage_control_sits_in_the_report_row(quart_app, monkeypatch):
_login(monkeypatch)
diff --git a/app/test_triage.py b/app/test_triage.py
index 58e3815..6a527e5 100644
--- a/app/test_triage.py
+++ b/app/test_triage.py
@@ -45,7 +45,7 @@ def _report(message_id="<ab...@cassandra.apache.org>", state="untriaged"):
def _config(monkeypatch, **overrides):
"""Config with triage on for cassandra, unless a test says otherwise."""
- settings = {"pmcs_with_triage": ["cassandra"], "pmcs_with_security_emails": []}
+ settings = {"pmcs_with_security_emails": []}
settings.update(overrides)
monkeypatch.setattr(triage.config, "get", lambda: types.SimpleNamespace(**settings))
@@ -136,24 +136,6 @@ def test_untriaged_has_a_form_and_other_states_do_not():
assert triage.form_template("cassandra", "non-issue-docs") is None
-def test_a_project_that_has_not_asked_for_triage_gets_no_form(monkeypatch):
- _config(monkeypatch, pmcs_with_triage=["kafka"])
- assert triage.form_template("cassandra", "untriaged") is None
-
-
-def test_triage_is_off_for_a_project_that_has_not_asked_for_it(monkeypatch):
- _config(monkeypatch, pmcs_with_triage=["kafka"])
- assert not triage.enabled_for("cassandra")
- assert triage.enabled_for("kafka")
-
-
-def test_a_decision_for_a_project_that_has_not_asked_for_triage_is_refused(monkeypatch):
- _config(monkeypatch, pmcs_with_triage=[])
- with pytest.raises(TriageError) as e:
- _decide({"message_id": "<ab...@cassandra.apache.org>", "action": "accept", "tag": "2024-03-01 a flaw"})
- assert e.value.status == 404
-
-
class _FakeResponse:
"""Just enough of an aiohttp response for `submit`."""
diff --git a/app/triage.py b/app/triage.py
index 0c2cdfc..024e7ea 100644
--- a/app/triage.py
+++ b/app/triage.py
@@ -25,9 +25,6 @@ dashboard entirely).
Which form a report gets, and which actions that form may submit, depend on the
state the report is in: both live in `_STATE_FORMS` below, so adding a form for
another state is a matter of adding an entry and a template.
-
-Triage is opt-in per PMC (`pmcs_with_triage` in the config), since a decision
-mails the reporter: `enabled_for` gates both the form and the endpoint.
"""
from app import config
@@ -146,17 +143,8 @@ class TriageError(Exception):
class TriageUnavailable(Exception):
"""The decision was valid, but could not be handed to the notification API."""
-def enabled_for(project: str) -> bool:
- """Whether `project` takes its triage decisions through this dashboard."""
- return project in config.get().pmcs_with_triage
-
def form_template(project: str, state: str) -> str | None:
- """The form to show for a report of `project` in `state`.
-
- None when the project has not asked for triage, or the state has no form.
- """
- if not enabled_for(project):
- return None
+ """The form to show for a report of `project` in `state`."""
form = _STATE_FORMS.get(state)
return form.template if form else None
@@ -193,9 +181,6 @@ def parse_decision(
payload, so a decision can only ever apply to a report of the project the
user was authorized for, in a state that has a form.
"""
- if not enabled_for(project):
- raise TriageError(f"{project} does not take triage decisions here", status=404)
-
message_id = _required_string(payload, "message_id")
tag = _required_string(payload, "tag")
raw_action = _required_string(payload, "action")
diff --git a/config.yaml.example b/config.yaml.example
index 8febad5..9dba744 100644
--- a/config.yaml.example
+++ b/config.yaml.example
@@ -12,10 +12,6 @@ pmcs_with_security_emails:
- ambari
pmcs_with_subprojects:
- commons
-# PMCs that take their triage decisions here; a decision mails the reporter,
-# so a PMC is only listed once it has asked for it
-pmcs_with_triage:
- - cassandra
# Retired PMCs whose reports the security team handles directly;
# committee ids from https://projects.apache.org/json/foundation/committees-retired.json
pmcs_in_attic: