The customer-portal squash inadvertently reverted the upstream/beta
fix from PR #427: production NODE_ENV was flipping the cookie Secure
flag back to hard `true`, which broke admin login on
HTTPS-frontend → HTTP-backend reverse-proxy stacks (browser drops
the Secure cookie over HTTP, login loops indefinitely).
Restored upstream/beta's tokenUtils.js verbatim and re-layered only
the customer cookie helpers (CUSTOMER_COOKIE_NAME,
setCustomerAuthCookie, clearCustomerAuthCookie,
getCustomerTokenFromRequest) on top.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Implements the recurring-customer login surface from
the-luap/picpeak#354 plugged into the maintainer's
new feature-flag infrastructure (PR #443) instead of
a parallel toggle.
* New `customerPortal` feature flag (foundation flag for the
not-yet-built calendar/quotes/bills/messaging customer
surfaces). Defaults FALSE on fresh installs, TRUE on existing
installs (events > 0) via migration 095 so live customer
accounts don't disappear mid-deployment.
* Foundation schema: customer_accounts, customer_invitations,
event_customer_assignments, customer_password_resets, plus
RBAC permissions customers.view / .create / .delete granted
to super_admin + admin system roles.
* Backend: /api/admin/customers (invite, list, search, assign,
deactivate, reset password) + /api/customer/auth/* +
/api/customer/* (login, dashboard, accept-invite, reset).
Customer JWT bypass minted via
/api/customer/events/:slug/access-token so existing gallery
middleware stays untouched.
* Frontend: /customer/* route tree gated by RequireFeature flag
customerPortal, with login / dashboard / accept-invite /
reset pages and a customer-side sidebar layout.
/admin/customers and /admin/customers/:id gated identically.
* Settings → Features grows a "Customers" section with a
Customer portal card. The maintainer's Features tab stays the
single source of truth — no parallel Advanced features tab.
* CustomerAccountPicker on event create/edit forms hides itself
when the flag is off; backend ignores customer_account_ids in
that case instead of erroring the whole event save.
Translations: en + de hand-translated. nl/pt/ru fall through to
en — flagged here as needing native review.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Addresses the-luap/picpeak#386 — gallery header layout cleanup.
- Drop the redundant "Menu" text label; menu button is icon-only with
tight padding (p-2).
- Absolute-position the menu icon at the very left of the header so it
no longer pushes the logo right with every other action. Logo wrapper
picks up pl-12 sm:pl-14 only when a menu button is rendered, so the
icon and logo don't overlap. When no menu button (controlsStyle:
classic), logo is flush with .container.
- New accent-coloured "Download" CTA placed immediately left of Logout.
Always visible when downloads are allowed; replaces the previous
primary-coloured "Download All" header button. Same CTA appears in
standard, hero, and minimal headers. Intentionally NOT shown in the
no-header variant (chromeless by design).
- Coloured via var(--color-accent) inline so the button automatically
tracks whatever palette the admin has chosen — works on plain beta
today (#22c55e) and auto-upgrades to the CI accent when #400 lands.
The sidebar's own Download All is untouched. Old showDownloadAll prop
stays on GalleryLayout for back-compat; GalleryView now passes
showDownloadAll={false} so only the new accent button renders in the
header.
Co-Authored-By: Claude Opus 4.6 <[email protected]>