fix(review-2): medium/low + docs — config validation, hygiene, doc sync

- compression_concurrency wired to boot config (state.rs) and removed as a
  dead admin control.
- patch_config gains per-key integer/range validation so numerically-valid-but-
  nonsensical values (-1/NaN/3.5) are rejected instead of silently reverting to
  default at read time.
- clearAuth now also clears the display name (shared-device residual).
- e2e/Caddyfile.test mirrors prod security headers + the SSE encode-exclusion so
  the test stack is representative and can catch header regressions.
- .gitignore: ignore root-level Playwright artifacts (test-results/, report).
- docs: USER_JOURNEYS §10 and SECURITY-BACKLOG updated to match the implemented
  read-only-ban behavior and the export-path fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
fabi
2026-07-02 22:19:56 +02:00
parent 80179357a7
commit b3d876fa85
8 changed files with 90 additions and 29 deletions

View File

@@ -4,7 +4,17 @@
# of HTTPS/Let's Encrypt.
:3101 {
encode zstd gzip
# Mirror prod: exclude the SSE stream from compression so buffering doesn't
# delay real-time events (and so the test stack exercises the real behavior).
@compressible not path /api/v1/stream
encode @compressible zstd gzip
# Mirror prod's security headers (minus HSTS, which is HTTPS-only).
header {
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Referrer-Policy "strict-origin-when-cross-origin"
}
reverse_proxy /api/* app:3000
reverse_proxy /media/* app:3000

View File

@@ -3,11 +3,26 @@
* flow. Centralising the API contract (routes, field names, expected statuses)
* means an API change is a one-file edit, not a 7-file hunt.
*/
import { uploadRaw, JPEG_MAGIC } from './upload-client';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { uploadRaw } from './upload-client';
import { db } from '../fixtures/db';
const BASE = process.env.E2E_FRONTEND_URL ?? 'http://localhost:3101';
// A real, decodable JPEG. Magic-bytes-only fakes now get auto-cleaned by the
// backend when compression fails (a failed transcode refunds quota + deletes the
// row), which would delete the seeded upload out from under the test. Read lazily
// at call time (cwd is the e2e dir at runtime, like the gallery-path spec) so test
// collection can't trip on a module-load read.
let sampleJpg: Buffer | null = null;
function sampleImage(): Buffer {
if (!sampleJpg) {
sampleJpg = readFileSync(join(process.cwd(), 'fixtures', 'media', 'sample.jpg'));
}
return sampleJpg;
}
export type SeedUploadOptions = {
caption?: string;
/** Mark compression done so the card is fully rendered in the feed. Default true. */
@@ -16,9 +31,7 @@ export type SeedUploadOptions = {
/** Seed a real, accepted upload owned by `jwt` and return its id. */
export async function seedUpload(jwt: string, opts: SeedUploadOptions = {}): Promise<string> {
const body = new Uint8Array(1024);
body.set(JPEG_MAGIC, 0);
const res = await uploadRaw(jwt, body, {
const res = await uploadRaw(jwt, sampleImage(), {
filename: 'a.jpg',
contentType: 'image/jpeg',
caption: opts.caption,