Commit Graph
21 Commits
Author SHA1 Message Date
popertots 6691cd5657 fix: rate-limit per-IP keying + dev no-op, admin 2FA recovery, 2FA account UI, admin modals, tip totals
Rate limiting (backend):
- RateLimit/ProgressiveRateLimit now derive the per-client key from
  CF-Connecting-IP, then chi's GetClientIP (the X-Real-IP value nginx sets at
  main.go:323), then RemoteAddr. Previously only CF-Connecting-IP/RemoteAddr
  were used, so behind the Docker nginx every client shared ONE bucket per
  limiter — 10 logins/min site-wide blocked all users (the reported
  'Error: Rate limit exceeded' after seeding was the login 10/min bucket
  tripped by the seed's 11 logins, all keyed 127.0.0.1 in dev).
- Real implementation is now //go:build !dev || test; new
  mw/ratelimit_dev.go (//go:build dev && !test) is a no-op passthrough, so
  'go run -tags dev' (the dev harness) never rate-limits dev/seeding traffic,
  while production and tests (-tags test,dev) keep the real limiter. The docs
  (Technical Manual) already claimed dev no-op behaviour — the code now
  matches. NewProgressiveRateLimiter is provided in the no-op build because
  tag-free ratelimit_shared.go:104 initializes the global at package init.

Admin 2FA management (backend):
- users.two_factor_last_used_at TIMESTAMPTZ column (init-script, fresh-DB).
- AdminUserDetail now returns twoFactorEnabled/twoFactorMethod/
  twoFactorLastUsedAt.
- New POST /api/admin/users/{id}/2fa/remove (admin-only): clears all 5 2FA
  columns + drops the user's in-memory attempt/lockout state — an admin
  recovery path when a user loses 2FA access.
- two_factor_last_used_at updated on every successful 2FA verification.

Account page (/account):
- 2FA section moved under the Notifications heading, visible to all roles;
  Email/SMS toggles (Notifications styling) acting as a radio group with
  'none' state; Apply button only when the selection differs from saved;
  unselecting shows a payment-rules warning dialog; the dev-comment
  '2FA is optional right now (REQUIRE_2FA is off)' and the 'Dev code:' debug
  line are removed.
- Cards tab hidden from admin role.

Admin modals:
- User Details modal: new 'Two-Factor Authentication' section above Patch
  Tests showing Enabled/Disabled, method, last-used timestamp, and a Remove
  2FA button with a confirmation dialog (POST to the admin endpoint, refetch
  on success).
- Booking Details modal: the customer's name now links to their User Details
  modal (optional openUserModal prop threaded through admin/+page and
  today/+page; other call sites unaffected).

Take Payment + /today:
- PaymentModal shows pre-tip (netTotal) and post-tip (totalWithTip) totals
  with a tip-amount delta row only when a tip is selected; zero-tip flow
  unchanged.
- The /today Payment button is hidden unless the booking is in_progress or
  completed, matching the backend gate (was shown for confirmed/pending
  bookings, producing the 'Booking must be in_progress or completed' error).

Verification: go test -tags test,dev -count=1 -parallel 8 ./... (20/20 ok
incl. new admin 2FA tests + mw tests), go build ./... and -tags dev both
compile, go vet clean, svelte-check 0 errors 0 warnings, env-docs gate OK,
docker compose config valid.
2026-08-22 00:34:49 +01:00
popertots 197d4c4b9b Gift-card rolling expiry, SvelteDate→Date purge, strict DST tests, UTC scan-location + settings legal floor
Gift-card rolling expiry (setting-driven, was dead config):
- GetGiftCardExpiryMonths(): single source of truth (business_settings
  gift_card_expiry_months, fallback 24) shared by payment handlers and the
  CleanupExpiredGiftCards job (was hardcoded 24).
- expiry_date now maintained on ALL 9 gift-card write sites (buy, topup,
  transfer, redeem, terminal payment, refund credit, till) so the refund-time
  guard at refunds.go actually fires. Schema default 12->24 + migration note;
  test-DB seed aligned. Stale "expiry_date IS NULL" test rewritten; new
  expired-card-rejected regression test.

Frontend SvelteDate purge (docs' stated convention, wide):
- All 180+ raw `new SvelteDate(...)` uses across routes/components replaced
  with parseWallClockDate (backend UTC ISO) or new Date (wall-clock
  constructors). SvelteDate imports removed. timeSlots.ts getDayWithOrdinal
  fixed. Zero SvelteDate references remain; svelte-check clean.

Strict timezone/DST testing + QA fixes:
- 8 new hermetic boundary tests: clock.DST transitions (both 2026 folds),
  closing-hours GMT vs BST, booking date-window midnight, refund-tier
  elapsed-time independence, deposit-window UTC-instant, scheduling
  LondonDateString midnight, today AT TIME ZONE window + UTC round-trip.
- today.go summary date labels fixed to London wall-clock (were showing the
  previous UTC day during BST) + regression test.
- pgx ScanLocation fixed to UTC via AfterConnect (was host-local -> JSON
  offsets depended on deployment TZ, contradicting the documented UTC
  invariant) + regression test. Registered as a new *Type to avoid a data
  race on the shared type map (caught by -race).

Admin Business Settings (setting now functional => legal floor):
- gift_card_expiry_months validation floor raised 1 -> 12 months (CMA/
  Consumer Rights Act 2015 unfair-contract-term guidance) in endpoint + UI,
  with rolling-expiry semantics shown in both display and edit form.
- 3 new expiry validation tests; 2 pre-existing message assertions updated.

Full suite 25/25 + race clean via run-tests.sh lockfile; svelte-check 0
errors/warnings; production build succeeds.
2026-08-22 00:34:49 +01:00
popertots eed8814021 fix: remove unused variables from Svelte components 2026-07-10 11:58:42 +01:00
popertotsandSisyphus 92124158bf feat(frontend): add apiFetch wrapper for automatic auth token injection
Centralizes auth token management into a reusable apiFetch() helper and getAuthHeaders() utility, eliminating inline Bearer token logic across all frontend files.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-07-06 19:21:34 +01:00
popertots 4af2b8dfb4 style: fix prefer-const and prettier formatting issues
Backend CI / Tests (push) Failing after 1m41s
Backend CI / Lint & vulns (push) Failing after 2m26s
Backend CI / Race detector (push) Failing after 3m45s
2026-06-25 13:48:03 +01:00
popertots ad0ad253ad style: apply prettier formatting to frontend
Backend CI / Lint & vulns (push) Failing after 1m59s
Backend CI / Tests (push) Successful in 2m1s
Backend CI / Race detector (push) Failing after 4m0s
2026-06-25 13:26:26 +01:00
popertotsandSisyphus 4ac7768070 refactor(frontend): timezone-safe date handling with London-aware utilities
Introduce getLondonTodayCalendarDate(), parseWallClockDate(), and formatLocalDateTime() for reliable Europe/London timezone handling. Replace ad-hoc SvelteDate/new Date() usage with these utilities across all components and stores.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-24 23:43:58 +01:00
popertotsandSisyphus d71373c7f2 feat(frontend): add VAT breakdown, print receipt, and VAT indicators
Add print receipt feature to UserBookingModal with full VAT breakdown. Fix VAT rate display (remove double *100). Show VAT breakdown (net + VAT) on booking confirmed page. Add VAT info to EditBookingModal. Show incl. VAT label on BookingFlow total, schedule, and today dashboard. Add VAT note to prices page. Show booking total amount on account page. Improve VAT enable toast in BusinessSettings.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-22 17:06:38 +01:00
popertotsandSisyphus 1a3829b4d9 feat(frontend): add former name display, referral discount type, and refunds to bookings
Update frontend types, stores, and components to support name history display and new API fields.

- Add previousFirstName/previousLastName to User type and BookingUser type
- Add referral discount_source type and refunds array to Booking type
- Create nameDisplay.ts utility for rendering '(formerly ...)' labels
- Create booking.ts utility for booking-related helpers
- Update 25+ admin, payments, today, and account components to display
  former names on booking cards, modals, appointment views, and user lists

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-20 16:59:31 +01:00
popertotsandSisyphus fa51c6b2f9 feat(frontend): update payments and today components
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-18 16:27:04 +01:00
popertotsandSisyphus bf90b0fa42 feat(frontend): add done-for-day summary card to CurrentAppointment, fix schedule z-index
Replace current/next card with done-for-day summary state when all appointments are finished. Shows daily stats (payments, tips, duration, customers) and week summary when tomorrow is closed. Fix schedule grid z-index to remove stacking context that caused overlay issues.

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-15 20:27:47 +01:00
popertotsandSisyphus 6e901690fd chore: apply project-wide formatting and UI library updates
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-29 20:23:14 +01:00
popertotsandSisyphus fc69fec361 refactor: today page components with calendar grid and stats
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-29 16:08:44 +01:00
popertotsandSisyphus f69750da82 feat: today calendar with time blockers, stats, and pending approvals improvements
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-28 16:34:13 +01:00
popertotsandSisyphus f553ebad99 fix: booking duration calculation, tip page auth, and UI polish across frontend
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-25 18:04:43 +01:00
popertots 2e1ab9d745 feat: Square payment integration, booking flow redesign, and timezone/weekday fixes
- Add Square payment integration (mock + handlers + UI): terminal/online payments,
  refunds, tips, saved cards, webhooks. Build-tagged dev/prod clients.
- Redesign booking flow: Step 4 conditional (deposit only), Step 5 confirmation
  screen with booking ID, auto-submit on transition.
- Redesign schedule modal: 2x3 button grid with Pay Deposit/Pay Early logic.
- Add deposit warning banner at Step 1 for users with outstanding deposits.
- Fix weekday conversion bug: Go 0=Sunday vs DB 0=Monday mismatch in 6 locations.
- Fix timezone bug: UTC vs London time in closing hours validation.
- Fix frontend error parsing: plain text backend errors now displayed correctly.
- Fix crypto.randomUUID fallback for environments without Web Crypto.
- Add 7 new regression tests: closing hours, advance check, active booking limit,
  weekday conversion, UTC/London, deposit snapshot, exceptional hours.
- Fix 3 flaky tests: dynamic dates instead of fixed, no-show timing.
2026-05-23 11:29:34 +01:00
popertots 80621e0d77 feat: add booking edit modal for /today page with service management
Replace placeholder BookingModal on the Next Appointment edit button with a
dedicated EditBookingModal that allows admins to add, remove, and override
services on an active booking. Includes backend PUT endpoint with overlap
detection and full test suite (20 tests).
2026-05-16 17:23:00 +01:00
popertots 44259a32ab ui: swap Cancel and Payment button layout in Next Appointment card
Cancel is now half-width (inline with Edit/Extend), Payment is full-width spanning bottom row
2026-05-10 20:02:18 +01:00
popertots 83c62ffb97 feat: edit request time blockers, today closing time, UI polish, and test fixes
- Add time blocker management for booking edit requests
- Add closing_time field to admin today/current-next endpoint
- Update UserBookingModal and CurrentAppointment UI components
- Fix fmt import in bookings_test.go (was missing)
- Fix created_by FK in TestAdminApproveEditRequest_TimeBlockerOverlap
- Update test coverage for edit request time blocker overlap
- Update gap backlog documentation
2026-05-10 16:53:17 +01:00
popertots 970cc5554d feat: add email verification, profile pictures, deposits, and calendar
export
Backend:
- Add email verification code generation and verification endpoints
- Add profile picture upload with S3 storage and image processing
- Add deposit_required field to users with 48h advance booking
  requirement
- Add loyalty stamps that accumulate on completed bookings
- Auto-transition bookings: confirmed → in_progress → completed
- Add booking cancellation handler with no-show detection
- Add ICS calendar file download endpoint for bookings
- Sync bookings to CalDAV on confirmation
  Frontend:
- Add schedule page route
- Add avatar and image-cropper UI components
- Update shadcn-svelte components (button, dialog)
- Add "Add to Calendar" button in booking modal
  Database:
- Add verification_codes table
- Add profile_pic_url, loyalty_stamps, deposits_required to users
- Various schema updates
2026-02-21 18:48:29 +00:00
popertots 3a8ea4c98f added booking approvals 2026-01-19 22:32:35 +00:00