Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions .changeset/identity-persistence-consent.md

This file was deleted.

22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Changelog

## 0.7.0

### Minor Changes

- 9ea1dfc: Identity, persistence & consent client layer (ADR-048) β€” same-session resume, cross-device "restore my chats", marketing consent, and a stable browser fingerprint.

**Persisted state (Zustand).** A framework-agnostic `zustand/vanilla` store with the `persist` middleware now keeps a small per-agent blob in localStorage (`smoo-chat-widget:<agentId>`): the session **pointer**, visitor identity (name/email/phone), marketing consent, a verified email, and the browser fingerprint. The **transcript is never persisted** β€” the smooth-operator server stays the source of truth and history is re-hydrated via `get_conversation_messages`. A `version` field drives `persist.migrate` so future shape changes upgrade old blobs in place; the storage adapter tolerates missing/locked-down localStorage (SSR, privacy mode) and never throws on boot.

**Browser fingerprint.** Every `create_conversation_session` now carries a stable `browserFingerprint` for anonymous-visitor correlation (and server-side CRM matching). Computed once and cached in the persisted store. Rather than pull in ThumbmarkJS β€” tens of KB and async device-probing, too heavy for an embed whose whole point is staying out of the host's LCP/TBT budget β€” the fingerprint is a persisted random UUID (the exact same-browser correlator) suffixed with a small FNV hash of a few non-invasive, stable signals (UA, language, timezone, screen). No canvas/WebGL/audio probes, no network, XSS-safe. Tradeoff: weaker cross-storage matching than a full device fingerprint, deferred to the server resolver, in exchange for a tiny, transparent, privacy-light token.

**Same-session resume.** On load, if a session pointer is persisted the widget calls `get_session`; when the session isn't `ended` it reuses the `sessionId`, replays history (`get_conversation_messages`, newest-first β†’ reversed to chronological), skips the pre-chat form, and continues the conversation. An ended/404 session clears **only** the pointer (identity & consent survive) and starts fresh.

**Returning-visitor resume by fingerprint (HTTP).** When there is no persisted pointer, the widget first `POST`s `/internal/resume-by-fingerprint` on the chat-ws wrapper with the browser fingerprint; if the wrapper resolves (and primes) a recent session it returns `{ resumable: true, sessionId, … }` and the widget adopts that session (then `get_session` + `get_conversation_messages` to hydrate) instead of creating a new one. `{ resumable: false }` falls through to a normal create.

**Pre-chat form: phone + marketing consent.** The phone field is now shown by default (optional; rides session `metadata.userPhone`). Two explicit, default-unchecked consent checkboxes (email + SMS) capture marketing opt-in; ticking one stamps a `consentAt` ISO timestamp, and the consent record (`{ emailOptIn, smsOptIn, consentSource: 'chat-widget-prechat', consentAt }`) threads into the session metadata. New config flags: `collectPhone`, `collectConsent`, `allowChatRestore` (all default `true`).

**Cross-device "Restore my chats."** An explicit footer affordance (not a mid-turn agent pause) runs the identity OTP flow over the chat-ws wrapper's HTTP routes β€” `POST /internal/identity/request-otp` β†’ `verify-otp` β†’ `resolve` β€” reusing the existing OTP UI. On a resolved list the visitor picks a conversation to replay (`get_session` + `get_conversation_messages`); the verified email is persisted.

**HTTP, not WS frames.** The smooth-operator engine (1.8.0) owns the `/ws` dispatch and rejects unknown verbs, so the cross-device identity flow and fingerprint resume are `fetch()` (POST, JSON) calls to the chat-ws wrapper, with the HTTP base derived from the WS endpoint (`wss://ai.smoo.ai/ws` β†’ `https://ai.smoo.ai`). The browser sends `Origin` automatically (origin-allowlisted server-side) and each request carries `agentId`/`agentName` plus an optional pre-auth `authContext` (`{ userId, signature, timestamp }`) from the new `authContext` config option.

All server-supplied strings (masked destinations, conversation previews, history) are rendered via `textContent`, keeping the 0.6.0 XSS guarantees intact, and the new UI follows the Aurora-Glass styling.

## 0.6.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@smooai/chat-widget",
"version": "0.6.0",
"version": "0.7.0",
"description": "Embeddable AI chat as a framework-light web component β€” the Aurora Glass design, streaming replies, grounded sources, and per-brand theming. Speaks the smooth-operator WebSocket protocol.",
"license": "MIT",
"author": "SmooAI",
Expand Down
Loading