fix(review): address PR #787 review blockers — db-orm diagram, C4 diagram, UUID link text
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m50s
CI / OCR Service Tests (pull_request) Successful in 23s
CI / Backend Unit Tests (pull_request) Successful in 3m45s
CI / fail2ban Regex (pull_request) Successful in 48s
CI / Semgrep Security Scan (pull_request) Successful in 23s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m4s
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m50s
CI / OCR Service Tests (pull_request) Successful in 23s
CI / Backend Unit Tests (pull_request) Successful in 3m45s
CI / fail2ban Regex (pull_request) Successful in 48s
CI / Semgrep Security Scan (pull_request) Successful in 23s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m4s
- db-orm.puml: replace geschichten_documents with journey_items, add type column to geschichten, bump schema version to V72
- l3-backend-3g-supporting.puml: update GeschichteController and GeschichteService descriptions to mention STORY/JOURNEY subtypes and JourneyItem
- geschichten/[id]/+page.svelte: replace raw UUID fallback with m.geschichten_document_link_placeholder() i18n key
- messages/{de,en,es}.json: add geschichten_document_link_placeholder translation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,8 +16,8 @@ System_Boundary(backend, "API Backend (Spring Boot)") {
|
|||||||
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(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(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(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(geschCtrl, "GeschichteController", "Spring MVC — /api/geschichten", "CRUD for publishable stories (STORY) and reading journeys (JOURNEY). Returns GeschichteSummary projections for list; full Geschichte with JourneyItems for detail. 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(geschSvc, "GeschichteService", "Spring Service", "Manages story lifecycle (DRAFT → PUBLISHED with timestamp). Supports two subtypes: STORY (prose) and JOURNEY (ordered JourneyItem sequence). 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(exHandler, "GlobalExceptionHandler", "Spring @RestControllerAdvice", "Converts DomainException, validation errors, and generic exceptions to ErrorResponse JSON with machine-readable ErrorCode and HTTP status.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@startuml db-orm
|
@startuml db-orm
|
||||||
' Schema source: Flyway V1–V69 (excl. V37, V43 — intentionally removed)
|
' Schema source: Flyway V1–V72 (excl. V37, V43 — intentionally removed)
|
||||||
' Schema as of: V69 (2026-05-27)
|
' Schema as of: V72 (2026-06-08)
|
||||||
' ⚠ This is a versioned snapshot. Update when the schema changes significantly.
|
' ⚠ This is a versioned snapshot. Update when the schema changes significantly.
|
||||||
|
|
||||||
hide circle
|
hide circle
|
||||||
@@ -359,6 +359,7 @@ package "Supporting" {
|
|||||||
title : VARCHAR(255) NOT NULL
|
title : VARCHAR(255) NOT NULL
|
||||||
body : TEXT
|
body : TEXT
|
||||||
status : VARCHAR(32) NOT NULL
|
status : VARCHAR(32) NOT NULL
|
||||||
|
type : VARCHAR(32) NOT NULL
|
||||||
author_id : UUID <<FK>>
|
author_id : UUID <<FK>>
|
||||||
created_at : TIMESTAMP NOT NULL
|
created_at : TIMESTAMP NOT NULL
|
||||||
updated_at : TIMESTAMP NOT NULL
|
updated_at : TIMESTAMP NOT NULL
|
||||||
@@ -370,9 +371,13 @@ package "Supporting" {
|
|||||||
person_id : UUID <<FK>>
|
person_id : UUID <<FK>>
|
||||||
}
|
}
|
||||||
|
|
||||||
entity geschichten_documents {
|
entity journey_items {
|
||||||
|
id : UUID <<PK>>
|
||||||
|
--
|
||||||
geschichte_id : UUID <<FK>>
|
geschichte_id : UUID <<FK>>
|
||||||
document_id : UUID <<FK>>
|
document_id : UUID <<FK>>
|
||||||
|
position : INTEGER NOT NULL
|
||||||
|
note : TEXT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,7 +441,7 @@ audit_log }o--o| documents : document_id
|
|||||||
geschichten }o--o| app_users : author_id
|
geschichten }o--o| app_users : author_id
|
||||||
geschichten_persons }o--|| geschichten : geschichte_id
|
geschichten_persons }o--|| geschichten : geschichte_id
|
||||||
geschichten_persons }o--|| persons : person_id
|
geschichten_persons }o--|| persons : person_id
|
||||||
geschichten_documents }o--|| geschichten : geschichte_id
|
journey_items }o--|| geschichten : geschichte_id (ON DELETE CASCADE)
|
||||||
geschichten_documents }o--|| documents : document_id
|
journey_items }o--o| documents : document_id (ON DELETE SET NULL)
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|||||||
@@ -1037,6 +1037,7 @@
|
|||||||
"geschichten_published_on": "veröffentlicht am {date}",
|
"geschichten_published_on": "veröffentlicht am {date}",
|
||||||
"geschichten_persons_section": "Personen in dieser Geschichte",
|
"geschichten_persons_section": "Personen in dieser Geschichte",
|
||||||
"geschichten_documents_section": "Erwähnte Dokumente",
|
"geschichten_documents_section": "Erwähnte Dokumente",
|
||||||
|
"geschichten_document_link_placeholder": "Dokument öffnen",
|
||||||
"geschichten_card_heading": "Geschichten",
|
"geschichten_card_heading": "Geschichten",
|
||||||
"geschichten_card_write_action": "+ Geschichte schreiben",
|
"geschichten_card_write_action": "+ Geschichte schreiben",
|
||||||
"geschichten_card_attach_action": "+ Geschichte anhängen",
|
"geschichten_card_attach_action": "+ Geschichte anhängen",
|
||||||
|
|||||||
@@ -1037,6 +1037,7 @@
|
|||||||
"geschichten_published_on": "published on {date}",
|
"geschichten_published_on": "published on {date}",
|
||||||
"geschichten_persons_section": "People in this story",
|
"geschichten_persons_section": "People in this story",
|
||||||
"geschichten_documents_section": "Referenced documents",
|
"geschichten_documents_section": "Referenced documents",
|
||||||
|
"geschichten_document_link_placeholder": "Open document",
|
||||||
"geschichten_card_heading": "Stories",
|
"geschichten_card_heading": "Stories",
|
||||||
"geschichten_card_write_action": "+ Write a story",
|
"geschichten_card_write_action": "+ Write a story",
|
||||||
"geschichten_card_attach_action": "+ Attach a story",
|
"geschichten_card_attach_action": "+ Attach a story",
|
||||||
|
|||||||
@@ -1037,6 +1037,7 @@
|
|||||||
"geschichten_published_on": "publicada el {date}",
|
"geschichten_published_on": "publicada el {date}",
|
||||||
"geschichten_persons_section": "Personas en esta historia",
|
"geschichten_persons_section": "Personas en esta historia",
|
||||||
"geschichten_documents_section": "Documentos mencionados",
|
"geschichten_documents_section": "Documentos mencionados",
|
||||||
|
"geschichten_document_link_placeholder": "Abrir documento",
|
||||||
"geschichten_card_heading": "Historias",
|
"geschichten_card_heading": "Historias",
|
||||||
"geschichten_card_write_action": "+ Escribir historia",
|
"geschichten_card_write_action": "+ Escribir historia",
|
||||||
"geschichten_card_attach_action": "+ Adjuntar historia",
|
"geschichten_card_attach_action": "+ Adjuntar historia",
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ async function handleDelete() {
|
|||||||
href="/documents/{item.documentId}"
|
href="/documents/{item.documentId}"
|
||||||
class="block rounded border border-line bg-surface px-4 py-3 font-serif text-base text-ink hover:bg-muted"
|
class="block rounded border border-line bg-surface px-4 py-3 font-serif text-base text-ink hover:bg-muted"
|
||||||
>
|
>
|
||||||
{item.note ?? item.documentId}
|
{item.note ?? m.geschichten_document_link_placeholder()}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
Reference in New Issue
Block a user