Consolidated fix wave for 1 Critical + 6 Important findings from the final review before merge: - Critical: marking a booking completed no longer frees its booked_slots mirror row or the unique-slot index, closing a double-booking hole (new migration 20260812110508, with regression pgTAP tests added first and confirmed failing against the old trigger/index). - uploadSalonImage() now returns the storage-relative path instead of an absolute public URL, so products/services.image stays one consistent format. - The product/service Id field is disabled while editing, preventing accidental duplicate rows from an upsert keyed on a changed id. - Cancel / Mark completed in AdminBookings now require window.confirm, matching the existing delete-confirmation pattern. - /admin and any unmatched /admin/* path now redirect to /admin/products instead of rendering blank. - Public signup is disabled in supabase/config.toml, and ProtectedRoute adds a defense-in-depth check that the session belongs to the admin user id, not just that a session exists. - Product/service delete now surfaces a friendly message for FK-violation errors (23503) via a new friendlyError() helper, instead of a raw Postgres error string. Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
16 KiB
16 KiB