fix(audit): P0-P3 audit fixes — 838 ruff errors → 0, 30 F821 bugs fixed, 118 files changed
- P0: hooks.py 3-tuple fix, trigger_dispatcher Contract, contacts/plugin unregister_actions_by_owner - P0: 5 test files — check_permission mocks removed, hardcoded DB credential → env var - P1: attachment_service DmsFile via Contract helper, restore_registry/history_hooks dedup - P1: mail/plugin restore unregister, mcp_client datetime.now(UTC), saved_views/filters patterns - P1: ProtectedRoute fail-closed, 13 test assertion fixes (bcrypt, DB-URLs, SECRET_KEYs) - P2: deprecated notifications → post_system_message (3 files), forgejo Base, report_generator lazy import - P2: webhooks permissions, deps.py/roles.py plugin perms removed, import_export default - P2: address/tags/entity_links patterns removed, worker.py Contract-Umgehungen fixed - P2: 28 frontend TODOs (hardcoded constants, deprecated notification API) - P3: dead code, duplicates, deprecated imports, private attr, __import__ inline - P3: 8 frontend TODOs (LucideIcons, inline styles, XSS, i18n) - ruff: 838 → 0 (612 auto-fix + 246 manual + 27 F821 regression fix) - F821: 30 → 0 (AutomationDefinition, DmsFile, user_id, Path, Any, String) - Contract-Umgehungen: 2 neue gefunden (worker.py:169, worker.py:280) und gefixt
This commit is contained in:
+21
-18
@@ -21,8 +21,8 @@ import json
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any, TYPE_CHECKING
|
||||
from datetime import UTC, datetime
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import litellm
|
||||
|
||||
@@ -100,7 +100,7 @@ _PERMANENT_KEYWORDS = frozenset(
|
||||
|
||||
def _get_cost_key(tenant_id: uuid.UUID | str) -> str:
|
||||
"""Build the Redis cost-tracking key for the current month."""
|
||||
now = datetime.now(timezone.utc)
|
||||
now = datetime.now(UTC)
|
||||
month_str = now.strftime("%Y-%m")
|
||||
return f"cost:tenant:{tenant_id}:month:{month_str}"
|
||||
|
||||
@@ -204,7 +204,7 @@ async def _check_cost_alerts(
|
||||
return
|
||||
|
||||
thresholds = [0.50, 0.80, 1.00]
|
||||
now = datetime.now(timezone.utc)
|
||||
now = datetime.now(UTC)
|
||||
month_str = now.strftime("%Y-%m")
|
||||
|
||||
try:
|
||||
@@ -226,11 +226,11 @@ async def _check_cost_alerts(
|
||||
# Best-effort system notification
|
||||
if db is not None:
|
||||
try:
|
||||
from app.core.notifications import post_system_message
|
||||
# Need a user_id — try to find an admin for this tenant
|
||||
from sqlalchemy import select as sa_select
|
||||
|
||||
from app.core.notifications import post_system_message
|
||||
from app.models.user import User, UserTenant
|
||||
from app.models.role import Role
|
||||
|
||||
async with db.begin_nested() if db.in_transaction() else _NoopCtx():
|
||||
result = await db.execute(
|
||||
@@ -289,11 +289,12 @@ async def get_api_credentials(
|
||||
# Fallback to DB provider
|
||||
if db and tenant_id:
|
||||
try:
|
||||
from app.plugins.builtins.ai_assistant.contracts import get_default_provider
|
||||
|
||||
provider = await get_default_provider(db, tenant_id)
|
||||
if provider and provider.api_key:
|
||||
return provider.api_key, provider.base_url, provider.provider_type
|
||||
from app.plugins.builtins.contracts import get_contract
|
||||
ai_contract = get_contract("ai_assistant")
|
||||
if ai_contract is not None:
|
||||
provider = await ai_contract.get_default_provider(db, tenant_id)
|
||||
if provider and provider.api_key:
|
||||
return provider.api_key, provider.base_url, provider.provider_type
|
||||
except Exception:
|
||||
logger.debug("Failed to get provider from DB, falling back to env")
|
||||
|
||||
@@ -316,9 +317,11 @@ async def get_provider_compliance(
|
||||
if not (db and tenant_id):
|
||||
return None
|
||||
try:
|
||||
from app.plugins.builtins.ai_assistant.contracts import get_default_provider
|
||||
|
||||
provider = await get_default_provider(db, tenant_id)
|
||||
from app.plugins.builtins.contracts import get_contract
|
||||
ai_contract = get_contract("ai_assistant")
|
||||
if ai_contract is None:
|
||||
return None
|
||||
provider = await ai_contract.get_default_provider(db, tenant_id)
|
||||
if provider is None:
|
||||
return None
|
||||
return {
|
||||
@@ -449,7 +452,7 @@ def _extract_usage(response: Any) -> dict[str, int]:
|
||||
# ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
async def llm_complete(
|
||||
async def llm_complete( # noqa: ASYNC109
|
||||
model: str,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
@@ -459,7 +462,7 @@ async def llm_complete(
|
||||
api_base: str | None = None,
|
||||
provider: str | None = None,
|
||||
response_format: dict[str, Any] | None = None,
|
||||
timeout: int = DEFAULT_TIMEOUT,
|
||||
timeout: int = DEFAULT_TIMEOUT, # noqa: ASYNC109
|
||||
max_retries: int = DEFAULT_MAX_RETRIES,
|
||||
trace_id: str | None = None,
|
||||
tenant_id: uuid.UUID | str | None = None,
|
||||
@@ -578,7 +581,7 @@ async def llm_complete(
|
||||
raise last_exc
|
||||
|
||||
|
||||
async def llm_embed(
|
||||
async def llm_embed( # noqa: ASYNC109
|
||||
texts: str | list[str],
|
||||
model: str | None = None,
|
||||
db: AsyncSession | None = None,
|
||||
@@ -587,7 +590,7 @@ async def llm_embed(
|
||||
api_base: str | None = None,
|
||||
provider: str | None = None,
|
||||
dimensions: int | None = None,
|
||||
timeout: int = DEFAULT_TIMEOUT,
|
||||
timeout: int = DEFAULT_TIMEOUT, # noqa: ASYNC109
|
||||
trace_id: str | None = None,
|
||||
) -> list[list[float]]:
|
||||
"""Generic text embedding via LiteLLM.
|
||||
|
||||
Reference in New Issue
Block a user