Commit Graph

4 Commits

Author SHA1 Message Date
Peter Meier a2ca0db9ca feat(security+obs): SSRF allowlist, HTML sanitization, timing-safe tokens, fetch timeouts, structured logger
Deploy / verify (push) Successful in 56s
Deploy / deploy (push) Successful in 1m17s
Security:
  - cms-images / cms-files now share resolveCmsSource (cms-source.server.ts)
    which enforces an allowlist: asset filename, absolute path on the CMS
    host, or full URL exact-matching the configured CMS host+protocol.
    Foreign hosts, protocol-relative URLs and path traversal return 400.
  - markdown-safe.ts is the single configured marked entrypoint; it
    disables raw HTML rendering globally (renderer.html() returns ''),
    removing the inline script/iframe injection vector via markdown.
    All 8 marked imports across components and loaders now go through it.
  - sanitize-blocks.server.ts walks resolved page/post content and runs
    HtmlBlock html fields through sanitize-html with a tight allowlist
    (no script/style/on*, only youtube/vimeo/spotify iframes, mailto/tel
    plus http(s) schemes, target=_blank gets rel=noopener).
  - Webhook tokens (revalidate, cache/clear) compared via
    crypto.timingSafeEqual through auth-token.server.ts.
  - cms.ts wraps every fetch in cmsFetch(): 5 s default timeout via
    AbortSignal.timeout, override per call or globally via
    PUBLIC_CMS_FETCH_TIMEOUT_MS. Stops slow CMS responses from pinning
    SSR workers indefinitely.

Observability:
  - log.server.ts gives logWarn / logError / logInfo with scope + context;
    swallowed catch {} blocks in hooks, layout.server, +page.server,
    [...slug]/+page.server and sitemap now log instead of going silent.

Routing:
  - Legacy /blog, /blog/page/:n, /blog/tag/:t and /p/:slug stub routes
    deleted; their 301 redirects moved into hooks.server.ts so the
    request never enters the SvelteKit page pipeline.

Tests (vitest, server-side):
  - auth-token.server.test.ts (6 cases for constant-time compare)
  - cms-source.server.test.ts  (8 cases for SSRF allowlist)
  - sanitize-blocks.server.test.ts (9 cases for sanitizer + walker)
  All 23 green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 16:09:25 +02:00
Peter Meier 724b75b6bf feat(cms-images): forward dpr + format=auto to RustyCMS
Deploy / verify (push) Successful in 40s
Deploy / deploy (push) Successful in 1m2s
- Accept dpr query param (clamped 1..4) and include it in cache key so
  each density gets its own cached file.
- Accept format=auto and negotiate locally from the client's Accept
  header (avif > webp > jpeg) before building the cache key — concrete
  formats in the cache avoid cross-client leaks.
2026-04-23 13:36:38 +02:00
Peter Meier a139372ce2 feat(image): enhance image handling with focal points and responsive support
Deploy / verify (push) Failing after 14s
Deploy / deploy (push) Has been skipped
- Added support for extracting focal points and alt text from CMS image fields.
- Introduced responsive image handling in TopBanner component, allowing for AVIF/WebP sources and LQIP placeholders.
- Updated image transformation functions to accommodate focal point parameters for better cropping.
- Refactored image URL resolution logic across various components and routes to utilize new image field structure.
2026-04-18 00:42:33 +02:00
Peter Meier 2fef91a548 Initial SvelteKit frontend port of windwiderstand.de
Deploy / verify (push) Failing after 32s
Deploy / deploy (push) Has been skipped
Full parity with Astro site: content rows, post/tag routes, pagination,
event badges + OSM map, comments, Live-Search via /api/search-index,
CMS image proxy, RSS, sitemap.

Deploy: Dockerfile + docker-compose.prod.yml + Gitea Actions workflow
to build + push to git.pm86.de registry and ssh-deploy to Contabo.
2026-04-17 22:01:30 +02:00