feat: embed Chatwoot live-chat widget (destek.sase.tr)

Site-wide live-chat widget served from the self-hosted Chatwoot at
destek.sase.tr, with verified user identity and vehicle context.

- apps/web: lib/chatwoot.ts loads the SDK lazily (mirrors the PostHog
  init pattern), init in main.tsx, identify logged-in users in __root
  via a server-computed HMAC, and attach the viewed vehicle (VIN/brand/
  model) as contact custom attributes on the vehicle detail page.
- apps/api: GET /api/chatwoot/identity (AuthGuard-protected) returns
  HMAC-SHA256(user.id) so the widget can use verified identity.
- env: VITE_CHATWOOT_BASE_URL + VITE_CHATWOOT_WEBSITE_TOKEN (build-time,
  wired through docker-compose.coolify.yml build args + Dockerfile ARG)
  and CHATWOOT_HMAC_TOKEN (api runtime). All optional — widget and
  endpoint no-op when unset.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 19:28:50 +03:00
parent c7e59b90e0
commit 1787607be5
11 changed files with 194 additions and 1 deletions

View File

@@ -104,6 +104,11 @@ export const envSchema = z.object({
// Changelog automation (token-authed internal endpoint for Fusion webhook)
CHANGELOG_AUTOMATION_TOKEN: z.string().min(32).optional(),
// Chatwoot — HMAC secret for the verified live-chat widget identity
// (/api/chatwoot/identity → setUser identifier_hash). When unset, that
// endpoint returns 503 and the widget falls back to anonymous visitors.
CHATWOOT_HMAC_TOKEN: z.string().optional(),
});
export type Env = z.infer<typeof envSchema>;