Commit Graph

5 Commits

Author SHA1 Message Date
Marcel
58254b492b fix(security): add csrfFetch wrapper and apply to all client-side mutating requests
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m52s
CI / OCR Service Tests (pull_request) Successful in 21s
CI / Backend Unit Tests (pull_request) Successful in 3m48s
CI / fail2ban Regex (pull_request) Successful in 44s
CI / Semgrep Security Scan (pull_request) Successful in 20s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m4s
Introduces `csrfFetch` (= `makeCsrfFetch(fetch)`) in cookies.ts as a
drop-in fetch replacement that auto-injects X-XSRF-TOKEN on POST/PUT/PATCH/DELETE.

Previously 8 call sites sent mutating requests without the CSRF header —
annotation resize, comment POST/PATCH/DELETE, Geschichte CRUD, Stammbaum
relationship creation, bulk-edit PATCH, and file upload — all would fail
with CSRF_TOKEN_MISSING if the backend's cookie-based protection triggered.

All 14 client-side mutating fetches now use csrfFetch; withCsrf/makeCsrfFetch
remain in the API for injectable-fetch use cases (e.g. useTranscriptionBlocks).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 10:50:56 +02:00
Marcel
efcc347c00 refactor: move shared components to lib/shared/ sub-packages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 14:40:14 +02:00
Marcel
d6db7a07bd refactor: move shared utilities to lib/shared/ sub-packages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 14:35:15 +02:00
Marcel
74b13abf53 fix(geschichten): widen story body and lift section-header contrast
Story-detail body now uses an explicit Tailwind block-element selector
ruleset instead of the `prose` plugin, so the body fills the full max-w-3xl
parent width — previously `prose` clamped to ~65ch inside an already narrow
page.

GeschichtenCard heading and the "+ Geschichte schreiben" link now use
text-ink-2 (#4b5563 = 7.6:1 on white, AAA-passable) instead of text-ink-3
or text-ink/60. Same fix on the "+ Geschichte anhängen" link in the
Document drawer column and on the Personen / Dokumente section headers
on the story detail page.

Closes Leonie's review B1, B2 and S4 on PR #382.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 18:46:31 +02:00
Marcel
fe1014a08a feat(geschichten): add /geschichten routes (index, detail, new, edit)
- /geschichten — published-stories index with filter pills + "+ Neue Geschichte"
  for BLOG_WRITERs; supports ?personId and ?documentId pre-filtering
- /geschichten/[id] — reader detail with sanitised {@html} body, person and
  document chip sections, BLOG_WRITER edit/delete with confirm dialog
- /geschichten/new — editor with optional ?personId and ?documentId pre-fill
  (silent ignore on unknown IDs to avoid leaking entity existence)
- /geschichten/[id]/edit — editor populated from existing story; BLOG_WRITE
  guard redirects readers to the detail page

All routes load via createApiClient(fetch) with !response.ok error handling
following the project pattern; PATCH/DELETE go through raw fetch which the
Vite dev proxy / Caddy production proxy authenticates via cookie.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 17:54:31 +02:00