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:
Nora
2026-07-07 12:17:14 -06:00
parent aff3a13016
commit cc02cb99c5
2 changed files with 50 additions and 1 deletions
-1
View File
@@ -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