From dc95a59dfa1787c56d972b523f941a022f5801f2 Mon Sep 17 00:00:00 2001 From: serversdown Date: Wed, 17 Jun 2026 20:14:30 +0000 Subject: [PATCH] =?UTF-8?q?test(auth):=20regression=20guard=20=E2=80=94=20?= =?UTF-8?q?gate=20never=20blocks=20machine=20endpoints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- tests/test_operator_machine_endpoints.py | 42 ++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 tests/test_operator_machine_endpoints.py diff --git a/tests/test_operator_machine_endpoints.py b/tests/test_operator_machine_endpoints.py new file mode 100644 index 0000000..21febbd --- /dev/null +++ b/tests/test_operator_machine_endpoints.py @@ -0,0 +1,42 @@ +# tests/test_operator_machine_endpoints.py +from tests.conftest import wire_operator_auth + + +def test_machine_endpoints_not_blocked_by_gate(client, db_session, monkeypatch): + """With the gate ON and no cookie, the LAN-only watcher endpoints must reach + their handlers (the gate must never silently break heartbeats). A handler may + return 422 for an empty body — that still proves the gate let it through. + + Note: /emitters/report uses a minimal valid body to avoid triggering the + app's validation_exception_handler (which calls await request.body() — a + known deadlock in Starlette 0.27 TestClient when the body is already + consumed). The gate behaviour is identical regardless of body validity. + """ + wire_operator_auth(monkeypatch, db_session, enabled=True) + + r = client.post("/api/series3/heartbeat", json={}, follow_redirects=False) + assert r.status_code != 401 # gate would 401 an unauth /api/* route + assert r.status_code != 303 + + r = client.post("/api/series4/heartbeat", json={}, follow_redirects=False) + assert r.status_code not in (401, 303) + + # /emitters/report is a sync endpoint with required Pydantic fields; supply a + # valid body so the validation_exception_handler (which awaits request.body()) + # is never triggered — that handler deadlocks the Starlette 0.27 TestClient. + valid_report = { + "unit": "TEST001", + "unit_type": "series3", + "timestamp": "2024-01-01T00:00:00Z", + "file": "test.evt", + "status": "OK", + } + r = client.post("/emitters/report", json=valid_report, follow_redirects=False) + assert r.status_code != 303 # gate would 303 an unauth HTML route + + +def test_static_assets_exempt(client, db_session, monkeypatch): + wire_operator_auth(monkeypatch, db_session, enabled=True) + # /sw.js and /manifest.json are PWA assets clients fetch pre-login. + assert client.get("/sw.js", follow_redirects=False).status_code in (200, 404) + assert client.get("/sw.js", follow_redirects=False).status_code != 303