Run gofmt -w across the backend, normalising the manually-aligned := blocks
to the gofmt standard. No code behaviour changes.
Add Prettier (+ prettier-plugin-svelte) to the frontend with the SvelteKit
default config (tabs, single quotes) so formatting is reproducible, then run
it over the whole tree. Add format / format:check npm scripts and a
.prettierignore (build output, generated schema.ts, static assets).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
These endpoints had no Cache-Control, so the browser re-downloaded every
thumbnail on each grid mount (the client fetches them with an auth header,
which also bypasses default image caching). Returning to the grid after
viewing a file re-fetched the whole visible page of thumbnails. Add
Cache-Control: private, max-age=3600. Content is immutable per file id from
the client's perspective (there is no replace-content UI); a future replace
flow should cache-bust via a versioned URL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Upload and Replace buffered the entire request body into memory with no
size limit, so a few large uploads could OOM the server. The file
handler now wraps the request body in http.MaxBytesReader and rejects any
file larger than MAX_UPLOAD_BYTES (default 500 MiB) before it is buffered.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two broken-access-control holes:
- PUT/DELETE /files/:id/tags(/:tag_id) and GET /files/:id/tags went
straight to TagService with no ACL check, letting any authenticated
user read or rewrite tags on anyone's private files. The handlers now
require view (list) or edit (mutate) on the target file via new
FileService.AuthorizeView/AuthorizeEdit helpers.
- POST /files/import accepted an arbitrary host path from any user,
turning it into an arbitrary server-side file read. It is now
admin-only and the supplied path is confined to IMPORT_PATH.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>