The property was removed from NextRequest types in Next.js 15+ but is
still populated by hosting platforms (Vercel, Netlify, etc.).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Adjusted `generateScryptHash` parameter in plaintext fallback logic in `lib/auth.ts` to use `storedPassword` instead of the intermediate hashed value. This prevents users from getting locked out when they adopt the recommended hash.
- Enhanced plaintext fallback verification to hash `password` and `storedPassword` via keyed HMAC before executing `crypto.timingSafeEqual` to avoid potential timing attacks more securely.
Co-authored-by: ralksta <16941050+ralksta@users.noreply.github.com>
Replaced the unbounded `Promise.all` in `getMapData` with a chunked
fetching approach. This prevents Out of Memory crashes by limiting
the concurrent fetching of large arrays of assets to chunks of 10.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Update in-memory rate limiter to fail secure (reject new requests) when maximum capacity is reached, rather than evicting the oldest tracking entry. This prevents an attacker from bypassing their rate limit by flooding the store with spoofed `x-forwarded-for` IPs to intentionally trigger cache eviction. Also cleaned up temporary files and updated tests to verify the behavior.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Upgraded `encodeAssetId` and `decodeAssetId` to use `aes-256-gcm` (Authenticated Encryption) instead of `aes-256-cbc`.
AES-CBC lacks authentication, leaving it potentially susceptible to padding oracle attacks or ciphertext manipulation.
The new token adds a `v2:` prefix which strictly enforces AES-GCM while supporting legacy fallback for cached urls.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
- Implement an in-memory `Map` to cache parsed YAML objects.
- Use `structuredClone` to prevent caller mutations from corrupting the cached object state.
- Implement negative caching for missing files.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Avoids unnecessary O(N) memory allocation and copy by returning `Buffer.from(...)` directly since Buffer inherits from Uint8Array in Node.js.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Add Promise deduplication (request coalescing) to the `getAssetInfo`
method in `ImmichClient` (`lib/immich.ts`) to prevent concurrent
identical requests from firing multiple times to the Immich server.
This is particularly helpful when calling `Promise.all` on multiple
assets concurrently (e.g. hero images on the homepage or multiple
album cover placeholder hashes).
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
- escapeHtml() in MapView.tsx sanitises city/country/url/name before HTML injection
- HeroTextContent extracted to top-level component with explicit props (was nested inside async Server Component)
- rate-limit.test.ts: add evictIfFull stress test (6/6 pass)
- Remove dead theme preset (no CSS, not in DevToolbar)
- Extract from closure → module-level export in lib/config/index.ts
- Extract helper in app/[...path]/page.tsx to deduplicate password gate check
- Extract inner component in app/page.tsx (was 4× inline in minimal/fullbleed/mosaic/split)
- Add 8 unit tests for buildSubpageGrid covering undefined, subset fields, layout fallback, and all fields
- Cache up to 1000 entries for thumbHashToBlurDataUrl and thumbHashToDominantHex
- Evicts oldest entry when limit is reached (FIFO on Map insertion order)
- ~100x speedup for repeated decoding of same thumbhash
Closes#7
- Add SubpageSectionConfig type to schema.ts
- Update config parser to handle sections with album overrides
- Refactor SubpageGridView to render TOC + section headers
- Add base CSS for subpage-toc and subpage-section in globals.css
- Add theme-specific overrides for all 5 themes (minimal, editorial,
classic, noir, monograph)
- Update gallery.yaml.example and docs/gallery-config.md
- Extract EXIF and Swipe logic into custom hooks for Lightbox
- Extract Map layout data formatting into mapService
- Extract AlbumDetailView and SubpageGridView components from page router
- Restructure monolithic config.ts into clean config/ directory
- /map page with Leaflet (CartoDB dark tiles)
- Photos clustered by city/country (not per-photo)
- /api/map endpoint with encrypted cover asset IDs
- Configurable via gallery.yaml (map: true/false)
- Conditional nav link in header
- CSP updated for Leaflet CDN and tile servers
- Theme-aware popups with cover thumbnails and album links