fix(transcription): replace sendBeacon with fetch keepalive; add catch-all API proxy #304

Merged
marcel merged 7 commits from fix/204-transcription-beacon-proxy into main 2026-04-23 07:12:23 +02:00

7 Commits

Author SHA1 Message Date
Marcel
3488375ad5 fix(proxy): block proxy-connection hop-by-hop header from client responses
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m37s
CI / OCR Service Tests (push) Successful in 30s
CI / Backend Unit Tests (push) Failing after 2m47s
CI / Unit & Component Tests (pull_request) Failing after 2m34s
CI / OCR Service Tests (pull_request) Successful in 36s
CI / Backend Unit Tests (pull_request) Failing after 2m59s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 18:21:40 +02:00
Marcel
4109299447 fix(proxy): enforce body size limit on actual byteLength, not just Content-Length header
Chunked requests omit Content-Length entirely. The previous guard
only checked the header and was bypassed. Now the body is buffered
first and its byteLength is checked, catching both cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 18:17:00 +02:00
Marcel
8eba2cda7d test(proxy): add PATCH forwarding and absent Content-Length coverage
Closes the two untested code paths flagged in review:
- PATCH method routes to backend with correct URL
- Requests without Content-Length header pass through (NaN > n = false)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 18:12:06 +02:00
Marcel
4f840f677c refactor(proxy): rename +server.spec.ts → proxy.spec.ts
Eliminates the Vitest "Files prefixed with + are reserved" warning
on every test run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 18:05:29 +02:00
Marcel
61b89ac9e4 refactor(autosave): rename flushViaBeacon → flushOnUnload; add void to fire-and-forget fetch
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m27s
CI / OCR Service Tests (push) Successful in 31s
CI / Backend Unit Tests (push) Failing after 2m48s
CI / Unit & Component Tests (pull_request) Failing after 2m44s
CI / OCR Service Tests (pull_request) Successful in 29s
CI / Backend Unit Tests (pull_request) Failing after 2m46s
The sendBeacon name was misleading after switching to keepalive fetch.
Also adds a test to confirm flush is a no-op when pendingTexts is empty.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 16:46:58 +02:00
Marcel
e5a2a89582 feat(proxy): add 1MB body guard and full proxy test suite
Blocks requests with Content-Length > 1 048 576 bytes with 413.
Tests cover security guards, body limit, and response forwarding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 16:34:28 +02:00
Marcel
c47c802ef5 fix(transcription): replace sendBeacon with fetch keepalive; add catch-all API proxy
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m41s
CI / OCR Service Tests (push) Successful in 32s
CI / Backend Unit Tests (push) Failing after 2m49s
CI / Unit & Component Tests (pull_request) Failing after 2m43s
CI / OCR Service Tests (pull_request) Successful in 35s
CI / Backend Unit Tests (pull_request) Failing after 2m46s
sendBeacon always sends POST, but the backend expects PUT for block updates, so
saves were silently dropped on page unload.  Replace with fetch({ keepalive: true,
method: 'PUT' }) which survives navigation and uses the correct HTTP method.

Add a catch-all SvelteKit server route at /api/[...path] so all client-side API
calls work in production (without the Vite dev proxy).  More-specific routes
(/api/persons, /api/tags, /api/documents/[id]/file) keep precedence.

Closes #204

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 15:56:53 +02:00