docs(c4): add L3 backend 3e persons, 3f OCR, 3g supporting domains

This commit is contained in:
Marcel
2026-05-06 21:30:39 +02:00
committed by marcel
parent dbf19037fe
commit 421d7ffd37
3 changed files with 117 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
@startuml
!include <C4/C4_Component>
title Component Diagram: API Backend — Persons & Family Graph
Container(frontend, "Web Frontend", "SvelteKit")
ContainerDb(db, "PostgreSQL", "PostgreSQL 16")
System_Boundary(backend, "API Backend (Spring Boot)") {
Component(personCtrl, "PersonController", "Spring MVC — /api/persons", "Lists and searches family members. Returns documents sent by or received by a person, correspondent suggestions, and person summary with document counts.")
Component(relCtrl, "RelationshipController", "Spring MVC — /api/network, /api/persons/{id}/relationships", "CRUD for explicit person relationships and the full family network graph (nodes + edges) used by the Stammbaum view.")
Component(personSvc, "PersonService", "Spring Service", "Person CRUD, alias management, and merge operations (reassigns all document sender/receiver references before deleting duplicate persons).")
Component(relSvc, "RelationshipService", "Spring Service", "Manages explicit directional family relationships (PARENT_OF, SPOUSE_OF, SIBLING_OF, etc.) with optional date ranges and notes.")
Component(relInference, "RelationshipInferenceService", "Spring Service", "Computes transitive family relationships from explicit edges to infer grandparent/grandchild, aunt/uncle, and other extended-family links for the network graph.")
Component(personRepo, "PersonRepository", "Spring Data JPA", "Queries persons with name search (including aliases), correspondent discovery, person summaries with document counts, and merge/reassignment helpers.")
Component(relRepo, "PersonRelationshipRepository", "Spring Data JPA", "Reads and writes PersonRelationship records. Supports lookup by person ID, by relation type, and existence checks for deduplication.")
}
Rel(frontend, personCtrl, "Person requests", "HTTP / JSON")
Rel(frontend, relCtrl, "Relationship and graph requests", "HTTP / JSON")
Rel(personCtrl, personSvc, "Delegates to")
Rel(relCtrl, relSvc, "Delegates to")
Rel(relCtrl, relInference, "Queries inferred graph")
Rel(personSvc, personRepo, "Reads / writes persons")
Rel(relSvc, relRepo, "Reads / writes relationships")
Rel(relInference, relRepo, "Reads relationships for inference")
Rel(personRepo, db, "SQL queries", "JDBC")
Rel(relRepo, db, "SQL queries", "JDBC")
@enduml

View File

@@ -0,0 +1,41 @@
@startuml
!include <C4/C4_Component>
title Component Diagram: API Backend — OCR Orchestration
Container(frontend, "Web Frontend", "SvelteKit")
ContainerDb(db, "PostgreSQL", "PostgreSQL 16")
ContainerDb(minio, "Object Storage", "MinIO (S3-compatible)")
Container(ocrPy, "OCR Service", "Python FastAPI")
System_Boundary(backend, "API Backend (Spring Boot)") {
Component(ocrCtrl, "OcrController", "Spring MVC — /api/ocr", "REST entry point: trigger single or batch OCR jobs, stream progress via SSE, query job status, and manage training runs and per-sender models.")
Component(ocrSvc, "OcrService", "Spring Service", "Creates OcrJob and OcrJobDocument records, checks Python service health, and delegates async execution to OcrAsyncRunner.")
Component(ocrBatch, "OcrBatchService", "Spring Service", "Orchestrates multi-document OCR jobs, iterating documents and delegating each to OcrAsyncRunner.")
Component(ocrAsync, "OcrAsyncRunner", "Spring Component — @Async", "Async worker that streams OCR results from Python page by page, persists transcription blocks and annotations via domain services, and emits progress via SSE.")
Component(ocrClient, "RestClientOcrClient", "Spring Component", "HTTP client wrapping the Python service: POST /ocr/stream (NDJSON), /train, /segtrain, and /train-sender. Falls back from streaming to batch on 404.")
Component(ocrTraining, "OcrTrainingService", "Spring Service", "Orchestrates model training: exports training data as ZIP, calls Python /train or /segtrain, persists training metrics in OcrTrainingRunRepository.")
Component(ocrJobRepo, "OcrJobRepository, OcrJobDocumentRepository", "Spring Data JPA", "Reads and writes OcrJob and OcrJobDocument records. Tracks job status (RUNNING/DONE/FAILED), per-document progress, page counts, and error messages.")
}
Component(transcriptionSvc, "TranscriptionService", "Spring Service", "See diagram 3c. Called by OcrAsyncRunner to persist transcription blocks per page.")
Component(annotationSvc, "AnnotationService", "Spring Service", "See diagram 3c. Called by OcrAsyncRunner to persist OCR-generated annotation regions per page.")
Rel(frontend, ocrCtrl, "OCR trigger, status, and progress requests", "HTTP / JSON / SSE")
Rel(ocrCtrl, ocrSvc, "Single-document jobs")
Rel(ocrCtrl, ocrBatch, "Batch jobs")
Rel(ocrCtrl, ocrTraining, "Training runs")
Rel(ocrSvc, ocrAsync, "Delegates async execution")
Rel(ocrBatch, ocrAsync, "Delegates async execution")
Rel(ocrAsync, ocrClient, "Streams OCR results page by page", "HTTP / NDJSON")
Rel(ocrTraining, ocrClient, "Sends training data ZIP", "HTTP / multipart")
Rel(ocrClient, ocrPy, "POST /ocr/stream, /train, /segtrain, /train-sender", "HTTP / REST")
Rel(ocrAsync, transcriptionSvc, "Saves transcription blocks per page")
Rel(ocrAsync, annotationSvc, "Saves annotation regions per page")
Rel(ocrAsync, ocrJobRepo, "Reads / writes OCR job state")
Rel(ocrJobRepo, db, "SQL queries", "JDBC")
Rel(ocrAsync, minio, "Generates presigned URLs for PDF fetch", "S3 API")
Rel(ocrPy, minio, "Fetches PDF via presigned URL", "HTTP / S3 presigned")
Rel(ocrTraining, db, "Persists training run metrics", "JDBC")
@enduml

View File

@@ -0,0 +1,46 @@
@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