title is VARCHAR(255) with no planned service-level check; ADR-040's
consequences listed the optimistic-lock and forgery obligations for #775 but
not this one, so an over-long title would have surfaced as a raw
DataIntegrityViolationException -> HTTP 500. Mirrors GESCHICHTE_TITLE_TOO_LONG.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
createdBy/updatedBy are NOT NULL and createdAt/updatedAt/version are Hibernate-
populated on every persisted row, so per the CLAUDE.md rule they must carry
@Schema(requiredMode = REQUIRED) like id/title/type/eventDate/precision already
do. Keeps the generated TypeScript types honest if the entity ever reaches the
OpenAPI spec (responses in #775 are planned as views, per ADR-040).
Extends the #774 task list (which named only the five domain fields) per PR #816 review.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
idx_timeline_event_persons_event_id and idx_timeline_event_documents_event_id
duplicated the leading column of their composite primary keys — Postgres already
serves timeline_event_id lookups from the PK index, so the extra indexes only
added write overhead. The inverse-side indexes (person_id, document_id) stay;
they cover the FK cascade path.
Deviates from the #774 task list ("all four FK columns") per PR #816 review.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The entities_reside_in_domain_packages ArchUnit rule has a hardcoded
allow-list of domain packages; add ..timeline.. so TimelineEvent passes.
CI caught this — the new domain package was not yet whitelisted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add timeline/ to the root and backend package tables, TimelineEvent to the
domain-model entity tables, TimelineEvent/EventType/Zeitstrahl to the
glossary, a new l3-backend-timeline C4 component diagram, and the
timeline_events table + two join tables (with their CHECKs and cascade FKs)
to the db-orm and db-relationships ER diagrams. Bumps the db-orm snapshot to
V77.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Records the architectural commitment for the timeline domain: views-not-
entities for issue 3 (ADR-036 rationale), DatePrecision import coupling
(ADR-025), the UNKNOWN-forbidden / SEASON-APPROX-legal precision contract,
the strict biconditional RANGE CHECK as a deliberate divergence from
Document, the @Version + NOT NULL audit-trail decisions, the optimistic-
lock-to-conflict translation contract (CWE-209), the server-populated-only
createdBy/updatedBy forgery guard (CWE-639), and the EventType stable
frontend styling contract.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@DataJpaTest against real Postgres (never H2): required-field round-trip,
YEAR default, linked persons/documents, eventDateEnd null/range round-trip,
TEXT description with no length cap, both RANGE-invariant rejections, the
UNKNOWN-precision rejection (NOT_SUPPORTED so the constraint violation does
not poison the test transaction), version null-before-persist/0-after-save,
and a parameterized accept-side proving DAY/MONTH/SEASON/YEAR/APPROX all
persist. makeEvent() defaults createdBy/updatedBy to random UUIDs so every
red is red for the intended reason.
@SpringBootTest cascade guard: deleting a linked Person/Document via the
domain service drops the join row (verified by direct COUNT) and leaves the
event intact.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Creates timeline_events plus the timeline_event_persons and
timeline_event_documents join tables, all FK columns ON DELETE CASCADE
(a person/document delete drops the join row, the event survives —
V71-class hardening). Two CHECK constraints push integrity to Postgres:
chk_timeline_event_range enforces event_date_end non-null IFF RANGE (a
strict biconditional, intentionally tighter than Document's open-ended
ranges), and chk_timeline_event_precision forbids exactly UNKNOWN while
keeping SEASON/APPROX legal. FK and query-column indexes added up-front
to avoid the V62 retrofit debt. Forward-only, additive DDL.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Curated timeline event mirroring Document's date block (eventDate /
precision / eventDateEnd) so events and letters share one rendering path.
Audit footprint deliberately diverges from Document: @Version optimistic
lock plus NOT NULL createdBy/updatedBy for the multi-curator edit flow.
precision reuses document.DatePrecision (imported, not duplicated) and
defaults to YEAR. ManyToMany persons/documents with explicit @JoinTable +
@BatchSize, matching Document's join conventions.
Repository is empty for now with a TODO marker for the issue-5 per-person
filter query.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PERSONAL/HISTORICAL classify a curated timeline event. The string value
names are a stable frontend styling contract (family vs. muted world
accent) — no mapping layer; renaming requires a coordinated frontend
change. First piece of the new timeline domain (Zeitstrahl, issue #774).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>