Second item of the v1.0.6 backlog. The "front 500MB vs back 100MB" mismatch
flagged in the v1.0.5 audit turned out to be a misread — every live pair
was already aligned (tracks 100/100, cloud 500/500, video 500/500). The
real bug is architectural: the same byte values were duplicated in five
places (`track/service.go`, `handlers/upload.go:GetUploadLimits`,
`handlers/education_handler.go`, `upload-modal/constants.ts`, and
`CloudUploadModal.tsx`), drifting silently as soon as anyone tuned one.
Backend — one canonical spec at `internal/config/upload_limits.go`:
* `AudioLimit`, `ImageLimit`, `VideoLimit` expose `Bytes()`, `MB()`,
`HumanReadable()`, `AllowedMIMEs` — read lazily from env
(`MAX_UPLOAD_AUDIO_MB`, `MAX_UPLOAD_IMAGE_MB`, `MAX_UPLOAD_VIDEO_MB`)
with defaults 100/10/500.
* Invalid / negative / zero env values fall back to the default;
unreadable config can't turn the limit off silently.
* `track.Service.maxFileSize`, `track_upload_handler.go` error string,
`education_handler.go` video gate, and `upload.go:GetUploadLimits`
all read from this single source. Changing `MAX_UPLOAD_AUDIO_MB`
retunes every path at once.
Frontend — new `useUploadLimits()` hook:
* Fetches GET `/api/v1/upload/limits` via react-query (5 min stale,
30 min gc), one retry, then silently falls back to baked-in
defaults that match the backend compile-time defaults so the
dropzone stays responsive even without the network round-trip.
* `useUploadModal.ts` replaces its hardcoded `MAX_FILE_SIZE`
constant with `useUploadLimits().audio.maxBytes`, and surfaces
`audioMaxHuman` up to `UploadModal` → `UploadModalDropzone` so
the "max 100 MB" label and the "too large" error toast both
display the live value.
* `MAX_FILE_SIZE` constant kept as pure fallback for pre-network
render (documented as such).
Tests
* 4 Go tests on `config.UploadLimit` (defaults, env override, invalid
env → fallback, non-empty MIME lists).
* 4 Vitest tests on `useUploadLimits` (sync fallback on first render,
typed mapping from server payload, partial-payload falls back
per-category, network failure keeps fallback).
* Existing `trackUpload.integration.test.tsx` (11 cases) still green.
Out of scope (tracked for later):
* `CloudUploadModal.tsx` still has its own 500MB hardcoded — cloud
uploads accept audio+zip+midi with a different category semantic
than the three in `/upload/limits`. Unifying those deserves its
own design pass, not a drive-by.
* No runtime refactor of admin-provided custom category limits —
the current tri-category split covers every upload we ship today.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cleanup of dead code marked // DEPRECATED in veza-backend-api/internal/handlers.
Each symbol was verified to have zero callers across the codebase before
deletion (go build ./... + go vet ./... + go test ./internal/... pass).
Deleted:
- UploadResponse type (upload.go) — callers use upload.StandardUploadResponse
- BindJSON method on CommonHandler (common.go) — callers use BindAndValidateJSON
- sendMessage method on *Client (playback_websocket_handler.go) —
internal WS broadcast now goes through sendStandardizedMessage
Kept as tech debt (still actively used, refactor out of J3 scope):
- UploadRequest type (upload.go:23) — used by upload handler, refactor
requires migrating to upload.StandardUploadRequest with multipart binding
- BroadcastMessage type (playback_websocket_handler.go:53) — still the
channel type for legacy playback broadcasts and referenced in tests
Also in this day (already committed in parallel):
- veza-backend-api/internal/api/handlers/two_factor_handlers.go deletion
(had //go:build ignore, zero callers) — bundled into 7fa314866 by
concurrent work on .github/workflows/*.yml
seed-v2 investigation:
- No Go source for seed-v2 found — it was only a compiled binary
already purged in J1 (0e7097ed1). No code action needed.
Refs: AUDIT_REPORT.md §8.1, §12 item 1-2
SEC-06: GetUploadStatus now verifies that the authenticated user owns the
upload before returning status. Returns 404 for non-owners to prevent
information disclosure.
- Tests complets pour frontend_log_handler.go (12 tests)
- Tests couvrent NewFrontendLogHandler et ReceiveLog
- Tests pour tous les niveaux de log (DEBUG, INFO, WARN, ERROR)
- Tests pour gestion des erreurs et validation JSON
- Couverture actuelle: 30.6% (objectif: 80%)
Files: veza-backend-api/internal/handlers/frontend_log_handler_test.go
VEZA_ROADMAP.json
Hours: 16 estimated, 23 actual