• v0.18.4 — the truncation guard actually fires now
    Some checks failed
    Audit / cargo audit (backend) (push) Failing after 9m29s
    Audit / npm audit (frontend) (push) Successful in 59s
    Checks / Backend — cargo test + clippy + fmt (push) Failing after 59s
    Checks / Frontend — vitest + svelte-check (push) Failing after 5m40s
    Checks / Keepsake viewer — builds, self-contained, committed artifact in sync (push) Failing after 5m18s
    Checks / E2E — typecheck + lint (push) Failing after 37s
    E2E / Playwright E2E (chromium + webkit) (push) Failing after 8m55s
    E2E / Cross-UA smoke matrix (push) Failing after 4m2s

    fabi released this 2026-08-22 08:20:13 +00:00 | 3 commits to main since this release

    Frontend only. Backend unchanged since v0.18.0, no migration touched (31), so the
    app image is re-tagged and v0.18.3 remains a valid rollback target.

    v0.18.3's 400 branch was inert against the incident it was written for. It
    assumed axum's plain-text multipart rejection, but the upload handler pulls the
    fields itself and wraps MultipartError in AppError::BadRequest — so a truncated
    body arrives as a bad_request envelope, the guard evaluated false, and the
    guest's photo was still purged.

    The rule now keys on the message and lives in an exported isIncompleteBody,
    with tests transcribing responses captured from the running backend. Verified
    again here against a live truncated upload:

    {"error":"bad_request",
    "message":"Datei konnte nicht gelesen werden: Error parsing `multipart/form-data` request"}

    Matching an upstream Display string is the known weakness; a distinct backend
    code (body_incomplete) is the durable fix once an app release is due.

    Downloads