The OCR status check is now gated behind canWrite (readers do no write-path
work), so the two OCR-status page tests must render as a writer — OCR is a
writer action. Without canWrite the status check never fires and the "OCR
läuft" spinner never mounts. Fixes the CI regression introduced by confining
read-only users to the read view.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Round out the "read-only users can't write anything" boundary: a READ_ALL
principal is forbidden from posting a block comment, replying, and editing a
comment (the prior tests only used a no-authority principal for create).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move the hasTranscription existence query out of the shared getDocumentById
into a dedicated getDocumentDetail used solely by GET /api/documents/{id}.
The flag is only consumed by the detail page, so the extra EXISTS query no
longer runs for the many internal getDocumentById callers (e.g. the
Geschichte resolve loop and the dashboard resume path). Behaviour of the
detail endpoint is unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI happy path: seed a PDF document with a transcription block as admin, then
as the READ_ALL "reader" open it — assert the "Transkription lesen" control,
the read text, a plain "Transkription" header, and the absence of the
Lesen/Bearbeiten tabs (panel cannot switch to edit).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
On the document detail page, pass canEdit={canWrite} to the panel header,
guard onModeChange so a reader can never flip to edit, and default panelMode
to 'read' for readers. Thread canAnnotate={canWrite} through DocumentViewer
to PdfViewer so the annotation layer's canDraw (which also gates delete and
resize) is off for readers — they can open and read, but not draw, edit, or
delete. The writer-only OCR status check is also skipped for readers.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
TranscriptionPanelHeader gains a canEdit prop (default true). Editors keep
the Lesen/Bearbeiten segmented toggle; read-only users get a plain
"Transkription" heading instead of a lone single-option pill, while the
"N Abschnitte" status line stays visible.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
transcription_read_label ("Transkription lesen") for the read-only entry
control and transcription_panel_title ("Transkription") for the plain
header readers see instead of the Lesen/Bearbeiten toggle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirrors the new server-computed boolean on the document detail payload so
the frontend can gate the transcription entry control at first paint.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Read-only users will soon be able to open the transcription read view, so
the write endpoints become the real authorization boundary. Explicitly
assert a READ_ALL-only principal is forbidden from create/update/reorder/
review block writes and annotation create/patch (the prior tests only used
a no-authority principal).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
getDocumentById now populates a transient hasTranscription boolean so the
document detail page can gate the transcription entry control at first
paint (no client store, no full block fetch, no layout shift).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Domain-service wrapper over existsByDocumentId so other domains can ask
"does this document have any transcription blocks?" without reaching into
the repository.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cheap EXISTS query backing a server-side "has a transcription" signal so
read-only users can be offered the read view at first paint.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>