diff --git a/.env.example b/.env.example index 9bd9cbd3..a471730d 100644 --- a/.env.example +++ b/.env.example @@ -26,6 +26,10 @@ ORIGIN=http://localhost:13002 # shifted api host port, e.g. http://localhost:18000.) LQ_API_INTERNAL_URL=http://api:8000 +# Max request body donna-web accepts (adapter-node BODY_SIZE_LIMIT; its default is +# 512K, which breaks KB uploads >0.5MB). Units K/M/G, or 'Infinity' to disable. +DONNA_WEB_BODY_SIZE_LIMIT=512M + # --- Required backend secrets (no defaults; bring-up FAILS if unset). Dev values OK locally. --- POSTGRES_DB=lq_ai POSTGRES_USER=lq_ai diff --git a/docker-compose.release.yml b/docker-compose.release.yml index 18a547ba..8117a205 100644 --- a/docker-compose.release.yml +++ b/docker-compose.release.yml @@ -253,6 +253,8 @@ services: environment: ORIGIN: ${ORIGIN:-http://localhost:3000} LQ_API_INTERNAL_URL: http://api:8000 + # SvelteKit adapter-node defaults to 512K, breaking KB uploads >0.5MB with an opaque 500. + BODY_SIZE_LIMIT: ${DONNA_WEB_BODY_SIZE_LIMIT:-512M} ports: - '127.0.0.1:${DONNA_WEB_HOST_PORT:-3000}:3000' healthcheck: diff --git a/src/lib/server/releaseCompose.test.ts b/src/lib/server/releaseCompose.test.ts new file mode 100644 index 00000000..3dd57168 --- /dev/null +++ b/src/lib/server/releaseCompose.test.ts @@ -0,0 +1,22 @@ +// @vitest-environment node +import { describe, it, expect } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +// docker-compose.release.yml is a hand-maintained mirror (see its header comment) +// with no other test surface; these guards pin deploy-critical donna-web env so a +// re-sync against vendor/lq-ai cannot silently drop it. Vitest runs from the repo +// root, so process.cwd() resolves the top-level deploy files. +const read = (rel: string) => readFileSync(resolve(process.cwd(), rel), 'utf8'); + +describe('docker-compose.release.yml donna-web', () => { + it('raises the adapter-node body-size limit (default 512K breaks KB uploads >0.5MB)', () => { + const compose = read('docker-compose.release.yml'); + const donnaWeb = compose.slice(compose.indexOf('donna-web:')); + expect(donnaWeb).toContain('BODY_SIZE_LIMIT: ${DONNA_WEB_BODY_SIZE_LIMIT:-512M}'); + }); + + it('documents DONNA_WEB_BODY_SIZE_LIMIT in .env.example', () => { + expect(read('.env.example')).toMatch(/^DONNA_WEB_BODY_SIZE_LIMIT=/m); + }); +});