From 421d7ffd3790290339b043b9efc773af7ca19ee3 Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 6 May 2026 21:30:39 +0200 Subject: [PATCH] docs(c4): add L3 backend 3e persons, 3f OCR, 3g supporting domains --- .../c4/l3-backend-3e-persons.puml | 30 ++++++++++++ docs/architecture/c4/l3-backend-3f-ocr.puml | 41 +++++++++++++++++ .../c4/l3-backend-3g-supporting.puml | 46 +++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 docs/architecture/c4/l3-backend-3e-persons.puml create mode 100644 docs/architecture/c4/l3-backend-3f-ocr.puml create mode 100644 docs/architecture/c4/l3-backend-3g-supporting.puml diff --git a/docs/architecture/c4/l3-backend-3e-persons.puml b/docs/architecture/c4/l3-backend-3e-persons.puml new file mode 100644 index 00000000..47c884aa --- /dev/null +++ b/docs/architecture/c4/l3-backend-3e-persons.puml @@ -0,0 +1,30 @@ +@startuml +!include + +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 diff --git a/docs/architecture/c4/l3-backend-3f-ocr.puml b/docs/architecture/c4/l3-backend-3f-ocr.puml new file mode 100644 index 00000000..c465f72c --- /dev/null +++ b/docs/architecture/c4/l3-backend-3f-ocr.puml @@ -0,0 +1,41 @@ +@startuml +!include + +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 diff --git a/docs/architecture/c4/l3-backend-3g-supporting.puml b/docs/architecture/c4/l3-backend-3g-supporting.puml new file mode 100644 index 00000000..c1558c89 --- /dev/null +++ b/docs/architecture/c4/l3-backend-3g-supporting.puml @@ -0,0 +1,46 @@ +@startuml +!include + +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