fix(sp37-followup): remove dead /api/resubmit permissions entry
Followup #1 from the SP37 final-state tracker. The pre-existing ('POST', '/api/resubmit'): WRITE_ROLES entry only matched the exact path /api/resubmit (no children — the prefix-match logic requires the trailing slash for sub-paths). No route is registered at that path; the actual resubmit lives at /api/inbox/rejected/resubmit (which has its own entry). Removing the dead entry is fail-closed: any future request to /api/resubmit (or its descendants) returns None from allowed_roles, which means deny. Without this cleanup, the matrix silently granted WRITE_ROLES to a non-existent route. Tests (test_auth_permissions_matrix.py, 5 cases): * Exact path /api/resubmit not in PERMISSIONS * allowed_roles('POST', '/api/resubmit') is None * /api/resubmit/, /api/resubmit/anything all deny Pin the invariant so a future contributor can't re-add a dead prefix. TDD: tests written first, watched fail (5 fail with the dead entry), removed the line, tests pass (5 pass). Full SP37 chain (36 tests) passes with the change.
This commit is contained in:
@@ -82,7 +82,6 @@ PERMISSIONS: dict[tuple[str, str], set[Role]] = {
|
||||
("POST", "/api/inbox/payer-rejected"): WRITE_ROLES,
|
||||
("POST", "/api/reconcile"): WRITE_ROLES,
|
||||
("POST", "/api/reconciliation"): WRITE_ROLES,
|
||||
("POST", "/api/resubmit"): WRITE_ROLES,
|
||||
("POST", "/api/acks"): WRITE_ROLES,
|
||||
("POST", "/api/batches"): WRITE_ROLES, # /export-837 regenerates X12 from DB rows
|
||||
("POST", "/api/eligibility"): WRITE_ROLES,
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
"""SP37 follow-up #1: Fail-closed for unregistered paths.
|
||||
|
||||
The permissions matrix is fail-closed — endpoints not listed are denied
|
||||
(None). The pre-existing ``("POST", "/api/resubmit"): WRITE_ROLES``
|
||||
entry was a dead prefix that ONLY matched the exact path ``/api/resubmit``
|
||||
(which is not a registered route). The actual resubmit lives at
|
||||
``/api/inbox/rejected/resubmit`` (already covered by its own entry).
|
||||
|
||||
This test pins the fail-closed invariant: ``/api/resubmit`` MUST have
|
||||
no granted permission because no route is registered there. Without
|
||||
this test, a future contributor could re-add the dead entry (or any
|
||||
similar dead prefix) and the auth system would silently grant access
|
||||
to a non-existent path.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from cyclone.auth.permissions import PERMISSIONS, allowed_roles
|
||||
|
||||
|
||||
def test_api_resubmit_exact_path_not_in_matrix():
|
||||
"""``/api/resubmit`` (exact, no children) must NOT be in the matrix.
|
||||
|
||||
The actual resubmit endpoint is ``/api/inbox/rejected/resubmit``,
|
||||
which has its own entry. The pre-existing
|
||||
``("POST", "/api/resubmit"): WRITE_ROLES`` entry only matched the
|
||||
exact path ``/api/resubmit`` and never any real route.
|
||||
"""
|
||||
assert ("POST", "/api/resubmit") not in PERMISSIONS
|
||||
|
||||
|
||||
def test_api_resubmit_returns_none_via_allowed_roles():
|
||||
"""Fail-closed: ``allowed_roles("POST", "/api/resubmit")`` is None.
|
||||
|
||||
The matrix default is DENY. A registered entry that matches the
|
||||
path would return a non-empty set of roles; the absence of any
|
||||
entry should return None.
|
||||
"""
|
||||
assert allowed_roles("POST", "/api/resubmit") is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", [
|
||||
"/api/resubmit",
|
||||
"/api/resubmit/",
|
||||
"/api/resubmit/anything",
|
||||
])
|
||||
def test_api_resubmit_prefix_variants_all_deny(path):
|
||||
"""No path under ``/api/resubmit`` should match any permission entry."""
|
||||
assert allowed_roles("POST", path) is None
|
||||
Reference in New Issue
Block a user