Marcel
51c799e20e
test(transcription): add TranscriptionServiceTest with 13 unit tests
...
CI / Unit & Component Tests (push) Failing after 1m20s
CI / Backend Unit Tests (push) Failing after 2m32s
CI / E2E Tests (push) Failing after 1h22m5s
CI / Unit & Component Tests (pull_request) Failing after 1m35s
CI / Backend Unit Tests (pull_request) Failing after 2m46s
CI / E2E Tests (pull_request) Failing after 1h24m55s
Tests cover: getBlock (found, not found), createBlock (creates annotation +
block + version), updateBlock (text + label), deleteBlock (deletes block +
annotation, not found), reorderBlocks, getBlockHistory, sanitizeText (null,
max length, plain text preservation), listBlocks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-05 11:46:16 +02:00
Marcel
6463a32dfc
fix: address PR review feedback — security, architecture, dead code
...
Fixes from PR #178 review:
Migration fixes:
- V18/V19: fix FK references from app_users to users (correct table name)
- V18: change annotation_id FK from ON DELETE CASCADE to ON DELETE RESTRICT
(block is aggregate root, cascade flows from block, not annotation)
Backend fixes:
- TranscriptionService.deleteBlock(): remove userId param, delete block first
then annotation directly via repository (no ownership check — block owns annotation)
- TranscriptionService.sanitizeText(): remove flawed regex HTML stripping,
textarea content is plain text by design — just enforce max length
- TranscriptionBlockController.requireUserId(): throw DomainException.unauthorized()
instead of silently returning null on auth failure
- CreateTranscriptionBlockDTO: add @Min/@Positive validation on coordinates
- Add @Slf4j logging to TranscriptionService for create/delete operations
Frontend fixes:
- Delete DocumentBottomPanel.svelte entirely (issue #175 requirement)
- Remove redundant mode exclusivity $effect (handled at toggle call sites)
- Remove dead handleCommentClick + onCommentClick prop (comments are future work)
- Remove quote hint UI (depends on comment feature)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-05 11:43:35 +02:00
Marcel
1efd3d8e23
feat(transcription): add frontend transcription editing UI ( #176 )
...
CI / Unit & Component Tests (push) Failing after 1m27s
CI / Backend Unit Tests (push) Failing after 2m40s
CI / E2E Tests (push) Failing after 4m44s
CI / Unit & Component Tests (pull_request) Failing after 1m21s
CI / Backend Unit Tests (pull_request) Failing after 2m27s
CI / E2E Tests (pull_request) Failing after 4m47s
TranscriptionBlock.svelte: editable block card with auto-resize textarea,
per-block save indicator, turquoise focus border, delete with confirmation
TranscriptionEditView.svelte: right panel with sorted block list,
debounced auto-save (1.5s), beforeunload flush, empty state CTA
DocumentTopBar: add Transcribe/Done toggle with turquoise styling,
mode exclusivity (transcribe and annotate mutually exclusive)
Document detail page: split view in transcribe mode (PDF left, blocks right),
load/save/delete blocks via fetch, block focus syncs to annotation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-05 11:34:01 +02:00
Marcel
5211e0b9f7
feat(topbar): add expandable metadata drawer with Details toggle ( #175 )
...
- DocumentMetadataDrawer: 3-column grid (≥1024px), single-column mobile
Shows document date, location, status, person cards, tag chips
Person names link to /persons/{id}, tags link to filtered search
Empty states for missing persons/tags, receiver cap with expand button
- DocumentTopBar: "Details" toggle button with animated SVG chevron
44×44px tap target, aria-expanded, Svelte slide transition
Semantic color tokens for dark mode compatibility
- Remove DocumentBottomPanel from document detail page
Bottom panel replaced by topbar drawer for metadata access
Simplify +page.server.ts (remove comments loading)
Update page.server.spec.ts for new load signature
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-05 11:22:38 +02:00
Marcel
234f83c40b
feat(i18n): add translation keys for metadata drawer and transcription
...
Keys for #175 : doc_details_toggle, section headings, field labels, empty states
Keys for #176 : transcription mode, block editing, save states, comments, drawing hints
Error codes: TRANSCRIPTION_BLOCK_NOT_FOUND, TRANSCRIPTION_BLOCK_CONFLICT
All three languages: de, en, es
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-05 11:16:22 +02:00
Marcel
a46b1a2e84
feat(transcription): add backend entities, service, and controller
...
TranscriptionBlock entity with @Version optimistic locking
TranscriptionBlockVersion for edit history
TranscriptionService facade: CRUD, reorder, version history
TranscriptionBlockController: REST endpoints under /api/documents/{docId}/transcription-blocks
DTOs: Create, Update, Reorder
ErrorCode: TRANSCRIPTION_BLOCK_NOT_FOUND, TRANSCRIPTION_BLOCK_CONFLICT
DocumentComment: add block_id field for block-level comment threads
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-05 11:13:13 +02:00
Marcel
5231476c27
feat(transcription): add Flyway migrations for transcription blocks
...
V18: transcription_blocks table with optimistic locking version column
V19: transcription_block_versions for edit history capture
V20: add block_id FK to document_comments for block-level threads
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-05 11:12:08 +02:00
Marcel
46d64f50a5
docs(specs): add final specs for transcription feature
...
CI / Unit & Component Tests (push) Failing after 1m52s
CI / Backend Unit Tests (push) Failing after 2m54s
CI / E2E Tests (push) Failing after 1h13m6s
Three final UI/UX specs for the collaborative transcription system:
- expandable-metadata-header-spec: labeled "Details" toggle with drawer
- annotation-transcription-final-spec: annotation-backed transcription with block-level comment threads
- transcription-read-mode-final-spec: clean split read mode with flowing prose and scroll sync
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-05 09:27:22 +02:00
Marcel
1a57ec2036
feat(topbar): add divider between sender/receiver block and action buttons
...
CI / E2E Tests (pull_request) Failing after 1h16m31s
CI / Unit & Component Tests (push) Failing after 1m30s
CI / Backend Unit Tests (push) Failing after 2m29s
CI / Unit & Component Tests (pull_request) Failing after 1m30s
CI / Backend Unit Tests (pull_request) Failing after 2m29s
CI / E2E Tests (push) Failing after 1h12m24s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-02 11:52:38 +02:00
Marcel
e362bc4977
feat(topbar): remove DocumentStatusChip — status dot has no value for users
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-02 11:41:03 +02:00
Marcel
01ba0d4121
feat(topbar): make PersonChip a link to the person detail page
...
Consistent with the overflow pill popup which already linked to persons.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-02 11:40:18 +02:00
Marcel
2e6366faf7
feat(topbar): add topbar_overflow_suffix i18n key and use it in overflow pill button
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-02 11:39:34 +02:00
Marcel
9dd35999e0
fix(topbar): fix overflow pill popup clipped and hidden behind pdf viewer
...
Remove overflow-hidden from the main flex row — the inner min-w-0 flex-1
overflow-hidden title container already handles truncation. Add relative z-10
to the topbar wrapper so it stacks above the pdf viewer. Pill is now hidden
below md (matching the chip row) and shows +N at md, +N weitere at lg+.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-02 11:36:41 +02:00
Marcel
e94f43264c
fix(topbar): add overflow-hidden to flex row so long titles truncate instead of pushing kebab off-screen
...
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 10:23:32 +02:00
Marcel
da7f94de84
feat(topbar): hide sender→receiver chip row below md to make room for buttons
...
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 10:22:05 +02:00
Marcel
3f0b686963
feat(topbar): always show annotate-stop button — primary action, not hidden in kebab
...
CI / Unit & Component Tests (push) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 10:16:38 +02:00
Marcel
1e9ef63191
refactor(topbar): extract annotate/download actions as Svelte snippets, render in desktop + kebab
...
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 10:15:31 +02:00
Marcel
51348ad26a
feat(topbar): add mobile kebab menu for annotate/download actions hidden below md
...
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 10:11:50 +02:00
Marcel
dba1e2a8eb
fix(topbar): use Long-Arrow-Right icon for sender→receiver separator
...
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 10:05:03 +02:00
Marcel
654b1283c1
fix(topbar): replace → text char with degruyter arrow icon for reliable centering
...
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 09:59:43 +02:00
Marcel
c5b98af69b
fix(topbar): center arrow glyph vertically with inline-flex items-center
...
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 09:46:37 +02:00
Marcel
03e2382c8a
feat(topbar): increase arrow to 30px and fix vertical alignment with leading-none
...
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 09:37:28 +02:00
Marcel
528e1e05ea
feat(topbar): increase sender→receiver arrow size for visibility
...
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 09:35:30 +02:00
Marcel
c64abccf63
feat(i18n): add doc_panel_annotate_hint message key in de/en/es, use in AnnotateHintStrip
...
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 09:30:21 +02:00
Marcel
47960b5028
feat(topbar): scale action button text and icons to match surrounding text size
...
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 09:23:31 +02:00
Marcel
7f2940f0f2
feat(topbar): increase all font sizes and bar height by another 25%
...
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m23s
CI / Backend Unit Tests (pull_request) Failing after 2m38s
CI / E2E Tests (pull_request) Failing after 1h14m58s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 09:12:27 +02:00
Marcel
37d728b006
feat(topbar): increase all font sizes and bar height by 25% for legibility
...
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Backend Unit Tests (pull_request) Failing after 2m38s
CI / Unit & Component Tests (push) Has been cancelled
CI / E2E Tests (pull_request) Failing after 1h15m22s
CI / Unit & Component Tests (pull_request) Failing after 1m40s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 09:09:59 +02:00
Marcel
965087b787
Revert "feat(topbar): double all font sizes and increase bar height for legibility"
...
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m22s
CI / Backend Unit Tests (pull_request) Failing after 2m35s
CI / E2E Tests (pull_request) Failing after 1h16m54s
This reverts commit 1d2e6d7b86 .
2026-04-01 09:04:24 +02:00
Marcel
1d2e6d7b86
feat(topbar): double all font sizes and increase bar height for legibility
...
CI / Unit & Component Tests (pull_request) Failing after 1m54s
CI / Backend Unit Tests (pull_request) Failing after 2m55s
CI / E2E Tests (pull_request) Failing after 1h12m45s
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-01 08:52:23 +02:00
Marcel
0c40e10743
fix(topbar): add role=group to OverflowPillButton outer div — a11y warning
...
CI / Unit & Component Tests (pull_request) Failing after 3m32s
CI / Backend Unit Tests (pull_request) Failing after 3m5s
CI / E2E Tests (pull_request) Failing after 1h11m43s
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 23:17:11 +02:00
Marcel
358131ca34
feat(ui): replace DocumentTopBar with responsive orchestrator (issue #173 )
...
- Accent bar, h-12/h-14 responsive height, 44×44px back link touch target
- PersonChipRow with sender→receivers chips, overflow pill button at ≥768px
- DocumentStatusChip dot-only at ≥768px
- Edit/annotate/download actions with annotateMode wiring
- AnnotateHintStrip below main row when annotateMode active
- status field added to Doc type
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 23:11:11 +02:00
Marcel
c7af33b998
feat(ui): add OverflowPillButton — tooltip, Escape focus return, use:clickOutside
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 23:08:53 +02:00
Marcel
eafb566170
feat(ui): add PersonChipRow — sender→receivers chips, 2nd receiver hidden md:contents
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 23:00:32 +02:00
Marcel
624eb9e5d6
feat(ui): add OverflowPillDisplay — non-interactive aria-hidden +N span
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 22:58:47 +02:00
Marcel
7bd995a045
feat(ui): add AnnotateHintStrip — 18px hint strip, hidden md:flex, annotateMode gated
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 22:46:32 +02:00
Marcel
20dbe04d45
feat(ui): add DocumentStatusChip — dot-only status indicator, hidden md:block
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 22:43:15 +02:00
Marcel
c9211b3061
feat(ui): add PersonChip component — avatar initials, abbreviated prop
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 22:42:01 +02:00
Marcel
27254fb0ac
feat(utils): add personFormat utility module with 6 pure functions (TDD)
...
abbreviateName, formatXsMeta, personAvatarColor (djb2), formatDate,
statusDotClass, statusLabel — 27 tests all green
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 22:39:44 +02:00
Marcel
b5a68e69e2
refactor(actions): extract clickOutside to shared module, replace 5 inline copies
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 22:34:54 +02:00
Marcel
b1e959412f
feat(frontend): add xs breakpoint (375px) to Tailwind @theme
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 22:02:46 +02:00
Marcel
19035fbeab
fix(dashboard): move right column first in DOM for mobile-first upload zone
...
CI / Backend Unit Tests (pull_request) Failing after 2m37s
CI / E2E Tests (pull_request) Failing after 1h12m25s
CI / Unit & Component Tests (push) Failing after 1m21s
CI / Backend Unit Tests (push) Failing after 2m30s
CI / E2E Tests (push) Failing after 6m59s
CI / Unit & Component Tests (pull_request) Failing after 1m41s
On small screens the upload zone now appears above recent docs.
lg:order-last keeps it visually on the right at desktop width.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 20:42:37 +02:00
Marcel
79faee554a
fix(dashboard): reduce incomplete docs widget from 5 to 3 items to prevent scroll
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 20:40:02 +02:00
Marcel
5adef7bec5
refactor(dashboard): delete DashboardMentions component — notifications page exists
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 20:29:03 +02:00
Marcel
595c2eb987
test(e2e): Classic Split — right column absent for read-only user, present for admin
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 20:27:39 +02:00
Marcel
518019f099
chore(e2e): gitignore Playwright auth state — regenerate in CI via auth.setup.ts
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 20:26:01 +02:00
Marcel
38b8804b17
style(dashboard): bump stats footnote from text-xs to text-sm for legibility
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 20:24:47 +02:00
Marcel
81ed1ce3ed
test(admin): replace setTimeout timing hack with vi.waitFor in layout specs
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 20:23:05 +02:00
Marcel
92e7aa127c
feat(dashboard): Classic Split — 2-col layout, remove DashboardMentions widget
...
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Restructures the dashboard to a lg:grid-cols-[1fr_300px] split:
- Left column: DashboardRecentDocuments (with stats footnote)
- Right column: DropZone (canWrite) + DashboardNeedsMetadata (flex-1)
Adds showRightColumn guard (canWrite || incompleteDocs.length > 0) so
read-only users with a complete archive never see an empty 300px ghost
column. DashboardMentions is removed from the page; the file is kept.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 19:36:36 +02:00
Marcel
f618364632
feat(dashboard): add stats footnote and min-h touch target to DashboardRecentDocuments
...
Adds stats?: StatsDTO | null prop; renders a quiet footnote showing total
document and person counts. Guards on stats?.totalDocuments != null so
zero is shown but the footnote is absent when stats fails. Adds
min-h-[44px] to doc rows for WCAG 2.5.5 touch target compliance.
Adds dashboard_stats_documents/persons i18n keys in de/en/es.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 19:29:00 +02:00
Marcel
20923d04b6
feat(dashboard): replace notifications fetch with stats in server load
...
Removes /api/notifications from the dashboard widget fetches and replaces
it with /api/stats so the page no longer needs to own notification data.
Returns stats: StatsDTO | null (null on failure) instead of mentions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 19:23:31 +02:00