item-overrides.json is gitignored (runtime data), so vinylEnabled must
be settable from the admin UI rather than committed directly. Adds the
"Enable vinyl configurator" checkbox alongside the existing vinyl promo
toggle so production overrides can be managed without touching files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a per-letter vinyl text add-on tied to the Custom Vinyl Square item.
Customers pick a balloon shape (Heart/Star/Circle), type their message
(max 30 non-space chars, ASCII only — no emoji), and choose from 8 Google
Fonts rendered as live previews. Price updates in real time at $0.65/letter.
At checkout, vinyl orders expand to two Square line items: the 18" Shape
balloon at its catalog price and the Custom Vinyl service at the calculated
letter count price, with the font attached as a modifier.
Also adds a per-item admin toggle ("Suggest custom vinyl add-on") that shows
a promo note on any balloon's product modal pointing customers toward the
vinyl service.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
NODE_ENV=production sets Secure:true but the container may sit behind
an HTTP-only reverse proxy, causing browsers to reject the cookie.
COOKIE_SECURE=false in .env overrides the flag without changing NODE_ENV.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The osrm-backend image is too minimal to run any health probe.
Drop the healthcheck entirely and use a plain depends_on so the
shop starts after OSRM, without blocking on a health condition
that can never pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
/dev/tcp is bash-only and fails in the container's default sh.
Switch to a real HTTP check against the OSRM API root, and add a
30s start_period so Docker doesn't fail the check before the road
data finishes loading.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
catalog-cache.json and item-overrides.json are written at runtime by the
admin panel — they should not be in version control.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Security:
- Replace raw password cookie with HMAC-derived session token + constant-time compare
- Add rate limiting (5 attempts / 15 min) to admin login
- Atomic JSON writes via file-utils to prevent corruption on crash
- Tighten CSP headers; add Square CDN to style-src and font-src
- WebP conversion + 20 MB limit on admin image uploads
Checkout reliability:
- Delayed capture flow: pre-auth → calendar write → capture (never charge without booking)
- Derive payment idempotency key from SHA-256(nonce) to prevent nonce/key mismatch on retry
- Idempotency key persisted in localStorage; auto-retry on network failure
- Idempotent CalDAV writes using orderId-based UIDs; treat 412 as success
- User-friendly Square error messages instead of raw API detail strings
UX:
- Welcome modal + 5-step guided tour with spotlight and scroll-into-view
- Balloon release agreement checkbox required before payment
- 24-hour lead time enforced server-side in both delivery and pickup slot generators
- Fix Square card form race condition with double-rAF before attach()
- Tour hides Bulma modal-background for bright, unobscured modal steps
Notifications:
- Improved SMTP error logging; re-throw on failure so callers see it
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>