CmsService translate path returns per-locale drafts with degraded
fallback; multilingual CMS page gets an AI translate action. Service
test updated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Consent-filtered recipient resolution, SMTP send with test-mode ON by
default (EDM_TEST_MODE, campaign cap, per-minute rate), opaque
unsubscribe tokens with a public unsubscribe endpoint (no PII in
URLs/logs), and per-campaign send history via V53.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SearchAiService interprets the query via AiTextRouter and grounds
results on existing search providers; degraded fallback keeps plain
search working when AI is unavailable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PostgreSQL cannot infer the type of a bare bind in '(? IS NULL OR col = ?)',
failing GET /api/admin/messages with BadSqlGrammarException. Cast the
null-check occurrence to ::text (findAll category/locale, delete locale).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Unescaped <= at findProducts/findProduct broke SqlSessionFactory XML
parsing, crashing every new jar at startup; deploy rolled back to the
pre-V50 jar, so V50/V51 never reached prod and the admin demo account
lost event membership again (floorplan menu fell back to /home).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Floorplan/dashboard scoped menu resolves the target event from the
user workspaces; admin had zero event_member rows so clicks silently
landed on /home (perceived broken link). Idempotent V51 enrolls admin
as ORGANIZER of e-2026-live and e-2026-smf.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
POST .../auto-generate/interpret parses NL conditions into a clamped
AutoLayoutRequest via AiTextRouter (Claude, injection-guarded JSON-only
prompt; degraded:true fallback keeps manual form authoritative).
auto-generate?ai=true attaches metric-grounded pros/cons per option
(generation never blocked by AI failure). AutoLayoutDialog gains an NL
input bar + interpreted-note + AI summary cards with WISE AI label.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
KintexPrincipal.hasAccess/roleFor ignored global role_code=ADMIN, so
admin@ users got 403 on all event-scoped endpoints. Add isAdmin() and
treat ADMIN as hall-manager equivalent (all-event read + approve).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>