feat(auth,security,scheduling): JWT revocation, S3 fix, notes validation, docs, tests
- JWT revocation with JTI (UUID v4): in-memory tracking, POST /api/logout, refresh handler revokes old JTI, RequireAuth rejects revoked tokens - Fix extractKey for S3 portfolio deletion: extracts full key path from URLs instead of just filename, preventing orphaned storage files - Notes validation: max=1000000 on all 13 Notes fields across 4 booking structs - CharCounter: grapheme-aware counter (Intl.Segmenter), threshold 750K, color-coded, integrated into 6 booking/admin components - loginInProgress: timestamp-based tracking, 30s staleness, 20-entry cap (429), ticker cleanup for stuck entries - Profile picture 15MB client-side limit, portfolio 20MB backend limit - Exceptional scheduling: expand query start to Monday of week - TodayCalendar: week-range fetching, closing time indicator, short-day lunch skip - NavBar: link reorder, mobile burger badge, slide transition, backdrop - ImageUpload: 20MB limit with visual feedback - formatDateISO: shared YYYY-MM-DD utility, shouldApplyLunchProtection helper - Update README.md and all Obsidian docs (Overview, Technical, Admin, Future Work) - Add 28 new tests: JWT (11), auth handlers (7), portfolio extractKey (5), notes validation (5). go build + go vet clean with test,dev tags
This commit is contained in:
@@ -31,6 +31,19 @@ Nail salon booking platform — Go 1.25 backend + SvelteKit 5 frontend + Docker.
|
||||
- **Admin login redirect**: admins are redirected to `/today` after login instead of the home page
|
||||
- **Patch test duration on services**: `patch_test_duration_hours` exposed on Service type; creating a service with duration > 0 auto-creates a patch test record
|
||||
- **`created_by_name` on bookings**: admin booking details now show who created the booking (admin name)
|
||||
- **Exceptional scheduling fix**: exceptional application queries expand start to Monday of the week, fixing single-day queries missing Monday-based `week_start` records
|
||||
- **Portfolio image upload limits**: 20MB file size limit with visual feedback (red borders, error text), upload button disabled for oversized files
|
||||
- **NavBar enhancements**: admin links reordered (Today/Schedule promoted), unread notification badge on mobile burger icon, backdrop overlay + slide transition for mobile menu
|
||||
- **TodayCalendar improvements**: fetches working/available hours for full week range instead of single day, closing time indicator on timeline, skips lunch suggestion for short days (5h or less)
|
||||
- **Lunch protection refinement**: `shouldApplyLunchProtection()` skips lunch protection for days with 5 or fewer working hours
|
||||
- **`formatDateISO` utility**: new `formatDateISO(date)` function in `lib/utils/format.ts` returning YYYY-MM-DD format for API calls, later extracted to shared utilities
|
||||
- **JWT revocation with JTI**: every JWT carries a unique `jti` claim (UUID v4), in-memory revoked JTI tracking with 5-minute cleanup ticker, `POST /api/logout` endpoint revokes current token, refresh handler revokes old JTI before issuing replacement
|
||||
- **Portfolio image deletion fix**: `extractKey` correctly extracts full S3 key path from URLs instead of just the filename, preventing orphaned files in storage
|
||||
- **Notes validation**: all `Notes *string` fields across booking structs validated with `max=1000000` tag (13 fields across 4 files)
|
||||
- **CharCounter component**: reusable grapheme counter using `Intl.Segmenter`, shows counter only above 750K graphemes, color-coded (green <800K, yellow 800K-950K, red >950K), integrated into 6 booking/admin components
|
||||
- **loginInProgress rate limiting**: switched from `map[string]bool` to `map[string]time.Time` with 30-second staleness check, 20-entry cap (returns 429 when full), ticker goroutine cleans up stuck entries
|
||||
- **Profile picture upload limit**: 15MB client-side check before crop dialog in account page
|
||||
- **Portfolio image upload backend limit**: separate `portfolioBodyLimit` (20MB) applied to `/images` route, distinct from `uploadBodyLimit` (15MB) for profile pictures
|
||||
|
||||
## Project Structure
|
||||
|
||||
|
||||
Reference in New Issue
Block a user