feat(geschichten): show blog writers' own drafts on the Geschichten overview (#807) #813

Merged
marcel merged 13 commits from feat/issue-807-drafts-overview into main 2026-06-12 19:46:05 +02:00

13 Commits

Author SHA1 Message Date
Marcel
17b0625a73 fix(shared): null-harden settled() against placeholder slots
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 3m6s
CI / OCR Service Tests (pull_request) Successful in 23s
CI / Backend Unit Tests (pull_request) Successful in 4m11s
CI / fail2ban Regex (pull_request) Successful in 45s
CI / Semgrep Security Scan (pull_request) Successful in 24s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m8s
A Promise.resolve(null) placeholder (e.g. the gated drafts slot) fulfils
with a null value; settled() dereferenced v.response unconditionally and
threw. Now any nullish value resolves to null. Adds unit tests for all
settled() branches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 19:45:22 +02:00
Marcel
f26874937d test(geschichte): drop duplicate null-status security test
list_with_null_status_and_BLOG_WRITE_returns_PUBLISHED_not_all_stories
was byte-for-byte identical to the @DisplayName("security: ...") variant;
keep the named one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 19:44:48 +02:00
Marcel
52019f7e69 feat(geschichten): show Veröffentlicht heading when Entwürfe section is visible
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 5m52s
CI / OCR Service Tests (pull_request) Successful in 32s
CI / Backend Unit Tests (pull_request) Successful in 4m52s
CI / fail2ban Regex (pull_request) Successful in 50s
CI / Semgrep Security Scan (pull_request) Successful in 25s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m7s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:54:34 +02:00
Marcel
2185150990 test(geschichten/page): add failing tests for gated Veröffentlicht heading
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:53:48 +02:00
Marcel
439b2133bd feat(geschichten): add Entwürfe section above published list for blog writers
Drafts appear in a separate unfiltered section at the top of the overview,
clearly separated by a divider and labelled with the draft badge on each row.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:51:19 +02:00
Marcel
cb87695834 test(geschichten/page): add failing tests for Entwürfe section
RED: page does not yet render a drafts section.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:51:19 +02:00
Marcel
b626698543 feat(GeschichteListRow): show DRAFT badge on desktop meta column and mobile row
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:51:19 +02:00
Marcel
df66cf6605 test(GeschichteListRow): add failing tests for DRAFT status badge
RED: component has no draft badge yet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:50:54 +02:00
Marcel
d5bfe77a73 feat(geschichten): fetch own drafts in page loader for blog writers
Blog writers now get a separate resilient DRAFT fetch alongside the
PUBLISHED list. A network failure degrades to drafts: [] rather than
a 500, so the overview stays usable even if the draft fetch times out.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:50:54 +02:00
Marcel
66281c9929 test(geschichten): add failing tests for draft fetch in page loader
RED: loader does not yet call parent() or fetch DRAFT stories.
Also extracts settled<T>() helper to $lib/shared/server/settled.ts
and seeds makeData/callLoad factories with drafts/parent defaults.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:49:28 +02:00
Marcel
e3140c4f99 fix(geschichte): null status always resolves to PUBLISHED, fixing CWE-639
A blog writer passing null status previously forwarded null to the repository,
returning all stories including other authors' drafts. Now only an explicit
DRAFT request (blog writer only) scopes to the caller's own stories.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:48:38 +02:00
Marcel
4541f90ce8 test(geschichte): add security regression tests for CWE-639 null-status and DRAFT scoping
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:48:38 +02:00
Marcel
b37aa6155e test(geschichte): rewrite false-safety-net null-status tests to catch CWE-639
Rename list_passes_null_status_through_for_BLOG_WRITER_so_drafts_are_visible
to list_with_null_status_and_BLOG_WRITE_returns_PUBLISHED_not_all_stories and
rewrite to verify eq(PUBLISHED) is passed — this test is now RED against the
vulnerable list() implementation.

Strengthen list_forces_PUBLISHED_status_for_reader_without_BLOG_WRITE with
eq(PUBLISHED) and isNull() matchers — both tests are now real regression fixtures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:48:38 +02:00