refactor(#356): DSAR-Fachlogik vollstaendig aus dem Core extrahiert — dsar_collect/dsar_erase in die 5 beteiligten Contracts (contacts, mail, tasks, calendar, kommunikation); core/jobs.py sammelt/loescht nur Core-eigene Daten und iteriert generisch ueber die Plugin-Registry; neue Plugins liefern DSAR-Kategorien ohne Core-Aenderung; Counts-/Category-Keys unveraendert; tasks/contracts.py von Patch-Artefakt bereinigt
Check Cross-Plugin Imports / check (push) Has been cancelled

fixes #356
This commit is contained in:
Agent Zero
2026-08-27 18:09:15 +02:00
parent 092c2d20fb
commit ad5601eb7d
7 changed files with 228 additions and 153 deletions
+32
View File
@@ -13,6 +13,11 @@ instead of importing from internal modules directly.
from __future__ import annotations
from typing import Any
from sqlalchemy import or_, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.plugins.builtins.contracts import get_contract_registry
from app.plugins.builtins.tasks.models import Task
from app.plugins.builtins.tasks.services import (
@@ -45,6 +50,33 @@ class TasksContract:
# ─── models (read-only for queries) ───
Task = Task
@staticmethod
async def dsar_collect(
db: AsyncSession, tenant_id: Any, user_id: Any
) -> dict[str, Any]:
"""GDPR Art. 15: collect tasks owned by or assigned to the user."""
tasks = (
await db.execute(
select(Task).where(
or_(Task.owner_id == user_id, Task.assigned_to == user_id),
Task.tenant_id == tenant_id,
Task.deleted_at.is_(None),
).limit(1000)
)
).scalars().all()
return {
"tasks": [
{
"id": str(t.id),
"title": t.title,
"status": t.status,
"priority": t.priority,
"due_date": t.due_date.isoformat() if t.due_date else None,
}
for t in tasks
]
}
# ─── self-registration ───