April 6: Guards Before Validation, Logs Before Silence
Three small security-adjacent bug fixes — the FITS validator was loading the whole file before checking the size, the JWT middleware was swallowing validation failures silently, and a region endpoint was using assert for user input validation. Plus TypeScript 6 and a pile of feature ideas from the MAST Users Group winter report.
Developer Journal
File size check before content validation (#1027)
The FITS upload validator was doing file.read() to validate the content before checking the file size. For anyone uploading a 10 GB file on a 16 GB machine, that's a guaranteed OOM — the size check was happening after the expensive read.
Flipped the order: size check first against MAX_FITS_FILE_SIZE_BYTES, reject with a 413 if oversize, then validate content. Also added a streaming-friendly guard that reads the header (first 2880 bytes per FITS spec) separately from the full body, so the header-only validation path doesn't need to load the whole array payload into memory.
Log JWT validation failures instead of swallowing (#1028)
The JWT middleware caught SecurityTokenException and silently returned 401, which is the right client-side behavior but left the operator blind when a token was malformed, signed with the wrong key, or using an unsupported algorithm. Added structured logging at Warning level with the exception type and failure reason, scrubbed of the actual token value (we never want tokens in logs).
Also tagged with a correlation ID so the auth log entries can be joined to the request log entries when debugging a specific client failing auth.
Replace assert with HTTPException for region validation (#1026)
/region endpoint was using Python assert statements to validate the ra, dec, and radius parameters. Two problems: asserts get stripped when running with -O, and even without -O, an AssertionError bubbles up as a 500 rather than the intended 400. Replaced with raise HTTPException(status_code=400, detail=...) and specific messages per failed constraint.
Added tests for out-of-range values, negative radius, and non-numeric input to lock in the new contract.
Feature ideas from MAST Users Group report (#1029)
The MAST Users Group published their Winter 2025–2026 report. Went through it and captured the feature ideas that are in scope for this project — most are v2 or later, but worth having them filed:
- Interactive region selection with live MAST query updates
- Target-based similarity search weighted by MAST metadata (exposure time, filter, instrument)
- Batch mosaic jobs from a MAST search result set
- NIRSpec IFU cube rendering (v2, separate epic)
Added them to docs/feature-ideas.md with source citations pointing back to the report sections.
TypeScript 6.0.2
Dependabot's TypeScript major bump (5.9.3 → 6.0.2) went clean. The main 6.0 change for this codebase was stricter type narrowing in generic constraints, which caught one real issue (a SharedWith union type that was being spread without discrimination) already fixed on main. No other touch-ups needed.
What shipped
| PR | Title |
|---|---|
| #1029 | docs: add feature ideas from MAST Users Group Report Winter 2025-2026 |
| #1028 | fix: log JWT validation failures instead of swallowing silently |
| #1027 | fix: add file size check before content validation to prevent memory exhaustion |
| #1026 | fix: replace assert with HTTPException for region parameter validation |
| #946 | chore(deps-dev): Bump typescript from 5.9.3 to 6.0.2 in /frontend/jwst-frontend |