fix(auth): unify site-wide 401/403 semantics (cma-auth-401-403-unify-20260915)

require_auth now uses HTTPBearer(auto_error=False) and raises 401 explicitly
when the Authorization header is missing or non-Bearer, matching
require_auth_401. Unauthenticated requests are 401 for every user endpoint;
authenticated-but-forbidden (cross-entity / role) stays 403.

- app/auth_middleware.py: single optional bearer, 401 on missing token
  (require_auth_401 kept as a compatibility alias)
- tests: update 4 pre-existing cases that asserted 403 without a token
  (test_auth, test_reports, test_kpi_causality, test_expenses,
  test_api_auth_surface_20260914) - intentional behavior change
- add tests/test_auth_401_unification_20260915.py: sample + full sweep
  (all AUTHED GET routes -> 401), invalid token -> 401, cross-entity and
  role-denied still 403, bot channel (X-BOT-KEY) and public paths unchanged
This commit is contained in:
Hermes CI Fix
2026-09-15 17:00:52 +08:00
parent f1d61f337a
commit b796897f8c
7 changed files with 245 additions and 21 deletions
+2 -2
View File
@@ -348,6 +348,6 @@ class TestPermissions:
assert resp.status_code == 200
def test_no_token_denied(self, client: TestClient):
"""无token → 403(router级 require_role 直接拒绝,与 test_reports 约定一致)"""
"""无token → 401(语义统一 2026-09-15:未认证=401;router级 require_role 仍负责角色 403)"""
resp = client.get(BASE)
assert resp.status_code == 403
assert resp.status_code == 401