docs(timeline): pin relative issue ordinals to Gitea issue numbers

The issue body's milestone-relative ordinals ("issue 3", "issue 5") become
unreadable once the milestone closes. Resolved against the Zeitstrahl milestone:
issue 3 = #775 (CRUD API: service/controller/DTO), issue 5 = #777 (assembly
endpoint with the per-person filter). Mapping anchored by issue 6 = #778
(date-label helper) and issue 9 = #781 (curator forms) in #774's forward notes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-06-13 00:47:22 +02:00
parent 62b96f718f
commit 788a804810
4 changed files with 10 additions and 10 deletions

View File

@@ -23,11 +23,11 @@ audit footprint deliberately diverges (see below).
Curated timeline events are their own concern, not a Lesereise/`Geschichte` subtype.
The domain owns `TimelineEvent`, `EventType`, and `TimelineEventRepository`.
### 2. Responses (issue 3) will be views, not serialized entities
### 2. Responses (#775) will be views, not serialized entities
`TimelineEvent` has two LAZY `ManyToMany` collections (`persons`, `documents`) and
`open-in-view` is `false` — exactly the shape that motivated ADR-036 for `geschichte`.
Issue 3 must assemble `TimelineEventView`/`TimelineEventSummary` inside the service
#775 must assemble `TimelineEventView`/`TimelineEventSummary` inside the service
transaction; a serialized entity is a 500 waiting to happen. Decided up front so it is
not retrofitted later.
@@ -64,7 +64,7 @@ inferred. This divergence is deliberate: a future "bug fix" must not relax it to
`Document` has neither a version nor a creator. A curated entity edited by multiple curators
warrants real protection, so `TimelineEvent` adds:
- `@Version Long version` — optimistic locking for the multi-curator edit flow (issue 3).
- `@Version Long version` — optimistic locking for the multi-curator edit flow (#775).
Object `Long` (not primitive) so it is `null` before first persist; Hibernate sets `0` on
insert. The service **must** catch `ObjectOptimisticLockingFailureException` and translate
it to `DomainException.conflict(...)`. Without that translation a concurrent-write conflict
@@ -82,7 +82,7 @@ session principal before every `save()`, or the timestamp moves while the "who"
### 7. `createdBy`/`updatedBy` are server-populated only — never bound from client input
Both are set from the session principal in the service, never from a request body. Binding
them from client input is an authorship-forgery / mass-assignment vector (CWE-639). Issue 3's
them from client input is an authorship-forgery / mass-assignment vector (CWE-639). #775's
regression suite must include forgery cases on **both** write paths (`POST` body with
`createdBy`, `PUT` body with `updatedBy`) — create and update are separate binding paths, so
testing only one leaves half the vector open. The update test must assert `updatedBy` equals
@@ -108,5 +108,5 @@ the event intact (V71/ADR-032 hardening — a person delete must never 500).
`timeline_events`). No rollback script, no rollback test.
- The `timeline → document.DatePrecision` compile coupling is permanent until a shared-package
refactor; precedent already exists (`importing/DocumentImporter`, `person`).
- The service/controller/DTO layer (issue 3) inherits the view-assembly, optimistic-lock
- The service/controller/DTO layer (#775) inherits the view-assembly, optimistic-lock
translation, forgery-guard, and permission obligations recorded above.