fix(lint): resolve all ruff lint errors

Add ruff config to exclude alembic E402, SQLAlchemy F821, and pre-existing
E501 line-length issues. Auto-fix 69 unused imports and 2 f-strings without
placeholders. Manually fix 8 unused variables. Apply ruff format to 127 files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jason Staack
2026-03-14 22:17:50 -05:00
parent 2ad0367c91
commit 06a41ca9bf
133 changed files with 2927 additions and 1890 deletions

View File

@@ -49,6 +49,7 @@ def require_role(*allowed_roles: str) -> Callable:
Returns:
FastAPI dependency that raises 403 if the role is insufficient
"""
async def dependency(
current_user: CurrentUser = Depends(get_current_user),
) -> CurrentUser:
@@ -56,7 +57,7 @@ def require_role(*allowed_roles: str) -> Callable:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"Access denied. Required roles: {', '.join(allowed_roles)}. "
f"Your role: {current_user.role}",
f"Your role: {current_user.role}",
)
return current_user
@@ -82,7 +83,7 @@ def require_min_role(min_role: str) -> Callable:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"Access denied. Minimum required role: {min_role}. "
f"Your role: {current_user.role}",
f"Your role: {current_user.role}",
)
return current_user
@@ -96,6 +97,7 @@ def require_write_access() -> Callable:
Viewers are NOT allowed on POST/PUT/PATCH/DELETE endpoints.
Call this on any mutating endpoint to deny viewers.
"""
async def dependency(
request: Request,
current_user: CurrentUser = Depends(get_current_user),
@@ -105,7 +107,7 @@ def require_write_access() -> Callable:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Viewers have read-only access. "
"Contact your administrator to request elevated permissions.",
"Contact your administrator to request elevated permissions.",
)
return current_user
@@ -127,6 +129,7 @@ def require_scope(scope: str) -> DependsClass:
Raises:
HTTPException 403 if the API key is missing the required scope.
"""
async def _check_scope(
current_user: CurrentUser = Depends(get_current_user),
) -> CurrentUser:
@@ -143,6 +146,7 @@ def require_scope(scope: str) -> DependsClass:
# Pre-built convenience dependencies
async def require_super_admin(
current_user: CurrentUser = Depends(get_current_user),
) -> CurrentUser:

View File

@@ -20,32 +20,36 @@ from starlette.requests import Request
from starlette.responses import Response
# Production CSP: strict -- no inline scripts allowed
_CSP_PRODUCTION = "; ".join([
"default-src 'self'",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: blob:",
"font-src 'self'",
"connect-src 'self' wss: ws:",
"worker-src 'self'",
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'",
])
_CSP_PRODUCTION = "; ".join(
[
"default-src 'self'",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: blob:",
"font-src 'self'",
"connect-src 'self' wss: ws:",
"worker-src 'self'",
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'",
]
)
# Development CSP: relaxed for Vite HMR (hot module replacement)
_CSP_DEV = "; ".join([
"default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: blob:",
"font-src 'self'",
"connect-src 'self' http://localhost:* ws://localhost:* wss:",
"worker-src 'self' blob:",
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'",
])
_CSP_DEV = "; ".join(
[
"default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: blob:",
"font-src 'self'",
"connect-src 'self' http://localhost:* ws://localhost:* wss:",
"worker-src 'self' blob:",
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'",
]
)
class SecurityHeadersMiddleware(BaseHTTPMiddleware):
@@ -72,8 +76,6 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware):
# HSTS only in production (plain HTTP in dev would be blocked)
if self.is_production:
response.headers["Strict-Transport-Security"] = (
"max-age=31536000; includeSubDomains"
)
response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
return response

View File

@@ -178,7 +178,6 @@ async def get_current_user_ws(
Raises:
WebSocketException 1008: If no token is provided or the token is invalid.
"""
from starlette.websockets import WebSocket, WebSocketState
from fastapi import WebSocketException
# 1. Try cookie