Widget di chat incorporabili: architettura e sicurezza
Il loader in due passi e l'iframe sandboxed dietro il widget di Simmetric Chat, con sessioni isolate, rate limiting e accesso a strati alla base di conoscenza.
La vostra base di conoscenza è una superficie di prodotto
I documenti che il vostro team scrive - documentazione di prodotto, articoli di supporto, wiki interni - rispondono alle stesse domande che i visitatori del vostro sito si stanno già facendo. Un widget di chat incorporato trasforma quella base di conoscenza in una porta d'ingresso conversazionale: i visitatori chiedono con parole loro, e le risposte fluiscono con citazioni, fondate nei workspace che scegliete di esporre.
La parte difficile non è la chat; è incorporare software quasi-non-fidato nella pagina di qualcun altro senza diventare una superficie d'attacco. Il sistema di widget di Simmetric Chat - tier Enterprise - è costruito attorno a quel vincolo. Questo articolo percorre l'architettura: l'embed in due passi, il runtime sandboxed, l'isolamento delle sessioni, il rate limiting e il modello di accesso a strati alla base di conoscenza che decide cosa la domanda di un visitatore può e non può raggiungere.
L'embed in due passi: loader e iframe sandboxed
Il widget si spedisce in due passi, e la suddivisione è deliberata:
- Lo script loader. Aggiungete un tag script al vostro sito, puntato al servizio widget con il vostro ID widget. Il loader è un piccolo file JavaScript che crea un iframe nella pagina host.
- Il pannello iframe. L'iframe carica un'applicazione Preact autonoma - compilata come bundle IIFE con CSS in linea - che renderizza il pulsante flottante, il pannello di chat e ogni interazione dentro il proprio documento.
<script src="https://your-simmetric-chat.com/widget/loader.js?widgetId=WIDGET_ID"></script>Perché non iniettare l'interfaccia di chat direttamente nella pagina host? Perché l'interpolazione di stringhe di contenuto non fidato in una pagina host è il classico percorso XSS - e l'intero flusso di contenuti di un widget è quasi-non-fidato: contiene output del modello, estratti di documenti e input dei visitatori. Far girare l'interfaccia dentro un iframe sandboxed a origine opaca rimuove quella classe di rischio del tutto: il contenuto della chat non si esegue mai nel contesto della vostra pagina, e gli stili del widget non possono collidere con i vostri (né viceversa).
Le vecchie rotte di embed per interpolazione di stringhe sono state rimosse dal prodotto esattamente per quella ragione - il pattern in due passi non è una opzione tra tante, è l'embed. La compilazione IIFE del widget esiste per la stessa ragione: il pannello è un singolo file autonomo senza sistema di moduli e senza caricamento di asset esterni a runtime, il che mantiene prevedibile la superficie di rete dell'iframe.
Cosa gira dove
Il widget tocca tre processi, e conoscere la mappa dei confini spiega ogni proprietà di sicurezza che segue:
- Il server principale possiede CRUD e branding dei widget, il collegamento ai workspace, l'API interna che il servizio widget chiama e gli endpoint lead e analytics lato admin. L'intero router interno dei widget è vincolato alla feature - quando la feature widget è spenta, risponde
402su ogni rotta. - Il servizio widget è la superficie di embed pubblica: loader JS, HTML dell'iframe, creazione delle sessioni, consegna della configurazione in cache, il proxy SSE della chat verso il server principale e l'endpoint lead. Si autentica al server principale con una chiave API dedicata e porta i propri rate limiter.
- L'iframe è il client Preact: bootstrap della sessione, streaming SSE, visualizzazione delle citazioni, domande suggerite, gate di consenso e la scheda lead.
Il proxy della chat inoltra lo stesso formato di eventi dell'API di streaming interna - messaggi di stato, annunci di piano, token in streaming, citazioni ed eventi terminali done/error - così ciò che un visitatore sperimenta è la stessa pipeline che il vostro team usa internamente, con i permessi del widget.
Sessioni isolate per visitatori anonimi
I visitatori non si autenticano mai; il widget conia l'identità al posto loro. Quando il pannello si apre, richiede una sessione al servizio widget, che chiede al server principale di crearne una: un token esadecimale a 256 bit, server-side, con scadenza a 24 ore. Ogni richiesta successiva del widget valida contro quella sessione - nessun JWT dalle app dei vostri utenti, nessun cookie che attraversi origini, nessuna credenziale ambientale di alcun tipo.
L'isolamento delle sessioni è ciò che tiene lo stato di un visitatore fuori dalla portata di un altro: le conversazioni sono anonime, i contatori e lo stato dei rate limit si agganciano al token di sessione anziché a un IP o a un fingerprint, e la pagina host non vede mai il token - vive nello storage dell'iframe stesso, scambiato con l'host attraverso un piccolo protocollo postMessage versionato che entrambi i lati validano contro l'esatto contentWindow che si aspettano, così i messaggi contraffatti da altri script vengono ignorati.
La consegna della configurazione segue la stessa disciplina. La configurazione del widget - branding, messaggio di benvenuto, domande suggerite - è consegnata all'iframe attraverso un blocco JSON nel documento dell'iframe stesso, iniettato server-side, non attraverso parametri URL che un visitatore potrebbe manomettere. Il visitatore non può influenzare nulla che il server non risolva: un'aggiunta recente lo sancisce ulteriormente, permettendo alla configurazione di ogni widget di selezionare il provider LLM e il modello che serve le sue risposte di chat, risolti server-side su ogni richiesta di chat - mai forniti dal client.
Il rate limiting come contratto di superficie pubblica
Un widget è un endpoint pubblico sulla vostra infrastruttura, quindi il controllo degli abusi è parte dell'architettura, non un ripensamento. I limiti sono stratificati per superficie:
- Limiti di chat per sessione: 20 messaggi all'ora e 5 conversazioni al giorno per sessione; i limiti superati rispondono
429con un suggerimentoretryAfter, e il widget mostra un avviso di rate limit anziché fallire in silenzio. - Limiter API per chiave: le chiamate del servizio widget al server principale sono limitate per chiave API hashata, così un deployment malfunzionante non può esaurire la superficie condivisa.
- Limiter lead: l'endpoint di lead capture è il gate più stretto a 3 richieste all'ora, perché un modulo pubblico è esattamente dove si concentra l'abuso dell'automazione.
- CORS fail-closed: l'header
Origindi ogni richiesta è validato contro la lista delle origini consentite del widget stesso, modificabile dal pannello di amministrazione. Le richieste di preflight non consentite sono respinte - e se il controllo dell'origine non può consultare il database, l'accesso è negato anziché concesso.
Il risultato è una superficie di chat pubblica che degrada con garbo sotto carico o abuso anziché o collassare o escludere tutti.
Accesso a strati alla base di conoscenza
Un widget dovrebbe rispondere dalla conoscenza che intendete pubblicare - niente di più. La stratificazione dell'accesso è imposta strutturalmente anziché per prompt:
- Whitelist dei workspace. Ogni widget è collegato a uno o più workspace, e la whitelist è sostituita atomicamente a ogni aggiornamento. La conoscenza da cui un widget può attingere è esattamente l'unione delle collezioni vettoriali e dei documenti dei workspace collegati - un widget di supporto può vedere il vostro workspace di documentazione pubblica senza mai toccare i dati dei progetti interni.
- Vincolo di feature. La creazione di widget richiede il flag della feature widget e rispetta il limite numerico di widget del piano, così la superficie non può crescere in silenzio.
- Citazioni come confini. Le risposte fluiscono con citazioni che puntano solo nei workspace consentiti - un visitatore può verificare da dove viene una risposta, e la traccia delle citazioni non può puntare fuori dalla whitelist.
Il branding - colore primario, nome del bot, loghi, posizione - è configurazione per widget renderizzata tramite proprietà CSS personalizzate dentro l'iframe, così una consulenza può presentare l'assistente come cosa del proprio cliente. I deployment di tier Community ricevono default sensati applicati quando i campi sono vuoti; la personalizzazione completa e il white-labeling sono flag enterprise.
La checklist di sicurezza, riassunta
Ogni strato sopra esiste perché un widget è software che spedite dentro il confine di fiducia di qualcun altro:
- Loader in due passi + iframe sandboxed a origine opaca - nessun XSS tramite interpolazione di stringhe
- Configurazione iniettata dal server - nulla di rilevante per la sicurezza è fornito dal client
- Model pin risolto dal server - il modello che risponde non può essere manomesso dal browser del visitatore
- Sessioni anonime a 256 bit con scadenza a 24 ore - nessuna credenziale ambientale
- Rate limit a strati con
429+retryAfter- degradazione garbata sotto abuso - CORS dinamico fail-closed - la fiducia sull'origine decisa in esattamente un punto
- Whitelist dei workspace atomica - l'accesso alla conoscenza è strutturale, non sperato nel prompt
Dal pannello di amministrazione allo snippet funzionante il percorso è di minuti: create il widget, whitelistate i workspace, aggiungete le origini, incollate il tag script. La guida completa all'integrazione copre branding, il protocollo simmetric:* postMessage e il lead capture end-to-end.


