@startuml
!include <C4/C4_Component>

title Component Diagram: API Backend — Supporting Domains

Container(frontend, "Web Frontend", "SvelteKit")
ContainerDb(db, "PostgreSQL", "PostgreSQL 16")

System_Boundary(backend, "API Backend (Spring Boot)") {
    Component(auditSvc, "AuditService", "Spring Service — @Async", "Writes audit log entries asynchronously via a dedicated TaskExecutor, with transaction-aware logging to prevent deadlocks on concurrent saves.")
    Component(auditQuery, "AuditLogQueryService", "Spring Service", "Queries audit logs for activity feeds, pulse stats, recent contributors, and per-document history. Facade over AuditLogRepository.")
    Component(dashCtrl, "DashboardController", "Spring MVC — /api/dashboard", "REST endpoints for the user dashboard: recent document resume (/resume), weekly transcription pulse stats (/pulse), and activity feed (/activity) with kind filtering and pagination.")
    Component(statsCtrl, "StatsController", "Spring MVC — /api/stats", "Returns aggregate counts (total persons, total documents) for the UI stats bar.")
    Component(statsSvc, "StatsService", "Spring Service", "Queries aggregate counts: total persons and total documents.")
    Component(dashSvc, "DashboardService", "Spring Service", "Assembles the user dashboard: recent document resume (calls DocumentService + TranscriptionService), weekly transcription pulse stats, and activity feed with contributor avatars.")
    Component(notifCtrl, "NotificationController", "Spring MVC — /api/notifications", "REST and SSE endpoints for notification stream, history with filtering, read/unread state, and per-user preference management.")
    Component(notifSvc, "NotificationService", "Spring Service", "Creates REPLY and MENTION notifications, optionally sends email, marks as read, and pushes events to connected clients via SseEmitterRegistry.")
    Component(sseRegistry, "SseEmitterRegistry", "Spring Component", "In-memory ConcurrentHashMap of Spring SseEmitter instances per user. Handles registration, deregistration, and JSON event broadcasts.")
    Component(geschCtrl, "GeschichteController", "Spring MVC — /api/geschichten", "CRUD for publishable stories that link persons and documents. Requires BLOG_WRITE permission for write operations.")
    Component(geschSvc, "GeschichteService", "Spring Service", "Manages story lifecycle (DRAFT → PUBLISHED with timestamp). Sanitizes HTML body with an allowlist policy.")
    Component(exHandler, "GlobalExceptionHandler", "Spring @RestControllerAdvice", "Converts DomainException, validation errors, and generic exceptions to ErrorResponse JSON with machine-readable ErrorCode and HTTP status.")
}

Component(documentSvc, "DocumentService", "Spring Service", "See diagram 3b. Called by DashboardService to fetch document titles and resume data.")
Component(transcriptionSvc, "TranscriptionService", "Spring Service", "See diagram 3c. Called by DashboardService to fetch transcription block progress for resume.")

Rel(frontend, dashCtrl, "Dashboard requests", "HTTP / JSON")
Rel(frontend, statsCtrl, "GET /api/stats", "HTTP / JSON")
Rel(frontend, notifCtrl, "Notification stream and history", "HTTP / JSON / SSE")
Rel(frontend, geschCtrl, "Story requests", "HTTP / JSON")
Rel(dashCtrl, dashSvc, "Delegates to")
Rel(statsCtrl, statsSvc, "Delegates to")
Rel(statsSvc, db, "Reads aggregate counts", "JDBC")
Rel(dashSvc, auditQuery, "Fetches activity feed and pulse stats")
Rel(dashSvc, documentSvc, "Fetches document titles and resume data")
Rel(dashSvc, transcriptionSvc, "Fetches transcription block progress for resume")
Rel(notifCtrl, notifSvc, "Delegates to")
Rel(notifCtrl, sseRegistry, "Registers client SSE connection")
Rel(notifSvc, sseRegistry, "Broadcasts events to connected clients")
Rel(geschCtrl, geschSvc, "Delegates to")
Rel(auditSvc, db, "Writes audit_log", "JDBC")
Rel(auditQuery, db, "Reads audit_log", "JDBC")
Rel(notifSvc, db, "Reads / writes notifications", "JDBC")
Rel(geschSvc, db, "Reads / writes geschichten", "JDBC")

@enduml
