Security fixes: P0-P2 complete (22 fixes)

P0 (7): Auth-bypass removed, migrations fixed, plugin-upload disabled, RLS FORCE+WITH CHECK, plugin double-registration fixed, persistent volume, domain removed
P1 (11): User/tenant model, Redis centralized, worker separated, transactional outbox, XSS fixed, DMS chunked streaming, permissions unified, password reset, metrics secured, config/docs fixed, cross-tenant FK
P2 (4): Contact model normalized, cross-imports reduced 94%, commands+state machines for contacts/dms/mail/calendar, SPA path-traversal

8 new migrations, 99 unit tests, 13 commands, 8 contracts, 72 files changed
This commit is contained in:
Agent Zero
2026-07-25 21:03:46 +02:00
parent aaa7406929
commit 727d86614e
103 changed files with 6831 additions and 1053 deletions
+15 -9
View File
@@ -40,7 +40,7 @@ async def _get_llm_api_key(db: AsyncSession, tenant_id: uuid.UUID) -> tuple[str
Returns (api_key, base_url, provider_type).
"""
try:
from app.plugins.builtins.ai_assistant.services import get_default_provider
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
@@ -167,7 +167,7 @@ async def gather_context(
context["contact"] = _serialize_row(contact) if contact else None
# Last 10 mails
from app.plugins.builtins.mail.models import Mail
from app.plugins.builtins.mail.contracts import Mail
mail_result = await db.execute(
select(Mail)
@@ -203,7 +203,10 @@ async def gather_context(
context["companies"] = companies
# Upcoming calendar events
from app.plugins.builtins.calendar.models import CalendarEntry, CalendarEntryLink
from app.plugins.builtins.calendar.contracts import get_contract as get_calendar_contract
_cal = get_calendar_contract()
CalendarEntry = _cal.CalendarEntry
CalendarEntryLink = _cal.CalendarEntryLink
now = datetime.now(UTC)
event_result = await db.execute(
@@ -229,7 +232,7 @@ async def gather_context(
context["activities"] = [_serialize_row(a) for a in audit_result.scalars().all()]
elif entity_type == "mail":
from app.plugins.builtins.mail.models import Mail
from app.plugins.builtins.mail.contracts import Mail
result = await db.execute(
select(Mail)
@@ -303,7 +306,7 @@ async def gather_context(
context["contacts"] = contacts
# Mails for this contact
from app.plugins.builtins.mail.models import Mail
from app.plugins.builtins.mail.contracts import Mail
mail_result = await db.execute(
select(Mail)
@@ -315,7 +318,10 @@ async def gather_context(
context["mails"] = [_serialize_row(m) for m in mail_result.scalars().all()]
# Upcoming events
from app.plugins.builtins.calendar.models import CalendarEntry, CalendarEntryLink
from app.plugins.builtins.calendar.contracts import get_contract as get_calendar_contract
_cal = get_calendar_contract()
CalendarEntry = _cal.CalendarEntry
CalendarEntryLink = _cal.CalendarEntryLink
now = datetime.now(UTC)
event_result = await db.execute(
@@ -356,9 +362,9 @@ async def gather_context(
# Semantically similar entities via unified_search
try:
from app.plugins.builtins.unified_search.search_engine import (
find_similar_all_types,
)
from app.plugins.builtins.unified_search.contracts import get_contract as get_search_contract
_search = get_search_contract()
find_similar_all_types = _search.hybrid_search
context["similar"] = await find_similar_all_types(
db, entity_type, entity_id, tenant_id, limit=3