> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mattone.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Cache del token Kross sui siti di prenotazione diretta

> Perché ogni sito di prenotazione diretta collegato a KrossBooking deve riusare la stessa sessione, come è fatta la cache, cosa la impone (build, controllo di salute, avviso giornaliero) e cosa fare quando arriva un avviso.

Questa pagina serve a chi fa supporto tecnico sui siti di prenotazione diretta (`stay.{brand}.com`) e non ha il contesto. Leggila **prima** di toccare un sito che parla con KrossBooking e **ogni volta** che arriva l'avviso «cache token Kross non a posto».

## Il problema in tre righe

* KrossBooking ammette al massimo **50 sessioni attive per struttura** (identificativo struttura, `hotel_id`). Ogni accesso all'API apre una sessione (un *token*).
* Le sessioni **non si chiudono e non si revocano**: scadono da sole **7 giorni dopo l'ultimo uso**.
* Oltre le 50, Kross risponde **401 con `error_code 12`** («too many active tokens») a **ogni** chiamata di quella struttura: il sito non mostra più disponibilità e prezzi, e smettono di funzionare anche gli altri sistemi che usano la stessa struttura (per esempio gli strumenti dell'assistente). Non è un problema di credenziali e **non passa in pochi minuti**.

Un sito su Vercel gira su molte istanze che nascono e muoiono da sole. Se ogni istanza nuova apre la sua sessione, poche decine di riavvii al giorno bastano a riempire le 50 sessioni. Per questo **la sessione va riusata fra tutte le istanze**: è il compito della cache del token.

<Warning>**È già successo.** Un sito derivato dal template è andato online con la cache impostata solo a metà: le impostazioni esistevano per nome, lo store dietro no. Il codice della cache è costruito per non bloccare mai un accesso (se la cache non risponde, si autentica e basta), quindi nessun errore, nessun avviso: ogni riavvio ha aperto una sessione nuova finché il pool si è riempito e il sito si è rotto in produzione. Le difese descritte sotto esistono perché quella situazione non resti più invisibile.</Warning>

## Come è fatta la cache

Ogni sito ha **una** delle due cache (alcuni le hanno entrambe):

| Cache | Per chi | Cosa serve sul progetto Vercel |
| - | - | - |
| **Cache condivisa Mattone** — una tabella nel database di Mattone, una riga per struttura, letta e scritta solo tramite funzioni protette da un segreto condiviso | Siti **operati dal team Mattone**. È condivisa con la piattaforma e con il gateway dell'assistente: un token ottenuto da uno vale per tutti, sulla stessa struttura | **Tre** impostazioni: indirizzo del database, chiave pubblica del database, segreto condiviso del gateway |
| **Store KV del progetto** (Vercel KV o Upstash) | Siti di **studenti con un deploy proprio**, ai quali il segreto condiviso di Mattone non va consegnato | **Due** impostazioni, create **collegando davvero uno store** dalla scheda Storage di Vercel (scriverle a mano senza store dietro non funziona) |

<Note>**Eccezione voluta alla regola «niente nomi di variabili d'ambiente»** (decisione di Francesco, 08/10/2026): questa pagina serve al supporto tecnico interno, e senza i nomi esatti chi deve sistemare un sito non sa cosa impostare. Qui ci sono **solo i nomi, mai i valori**: i valori stanno nel Vault e su Vercel, non si scrivono in nessuna pagina né in chat.</Note>

Le impostazioni (variabili d'ambiente del progetto Vercel, ambiente **Production**):

| Cosa | Variabili obbligatorie |
| - | - |
| Il sito usa Kross (fanno scattare la guardia) | `KB_API_KEY`, `KB_HOTEL_ID` (più `KB_USERNAME`, `KB_PASSWORD` per autenticarsi) |
| Cache condivisa Mattone (tutte e tre) | `SUPABASE_URL`, `SUPABASE_ANON_KEY`, `GATEWAY_SHARED_SECRET` |
| Store KV del progetto (tutte e due) | `KV_REST_API_URL`, `KV_REST_API_TOKEN` |

Basta **una** delle due cache completa, con valori non vuoti. Nei siti la cui cache è solo la tabella condivisa (nessun modulo KV nel codice) le due variabili KV **non contano**: la build si ferma comunque se manca il trio.

Come lavora, in breve: il sito chiede prima il token alla cache; se c'è lo usa (nessuna chiamata a Kross); se manca, **una sola** istanza alla volta prende un «turno», si autentica e pubblica il token, le altre aspettano qualche secondo e lo riusano.

### Le regole del token (uguali per siti, gateway e piattaforma, dal 08/10/2026)

Con la cache condivisa Mattone i siti seguono **le stesse regole** dell'assistente e della piattaforma, descritte in [Token Kross (pool da 50)](/integrazioni/kross/token-pool):

* il token in cache **si riusa** anche quando la sua scadenza stimata è passata: lo decide Kross, rispondendo «token scaduto» (`error_code 2`);
* una nuova autenticazione si fa **solo se la cache la concede** (nessun altro sta autenticando, nessun freno, tetto non raggiunto) e ogni autenticazione riuscita viene **registrata**;
* su `error_code 12` si apre un **freno condiviso di 15 minuti** che ferma tutti i sistemi su quella struttura, e il token in mano **non si butta** (è l'unico che funziona);
* c'è un **tetto di 40 autenticazioni in 7 giorni** per struttura, sotto i 50 di Kross: superato, nessuno crea token finché una persona non capisce chi li sta consumando;
* su `error_code 2` il token si sostituisce **una volta** e la richiesta si ritenta **una volta**, mai in loop.

Nei siti con il solo store KV (senza la cache condivisa) valgono riuso, sostituzione una sola volta e niente autenticazioni in parallelo, ma il freno vale solo per la singola istanza e il tetto non c'è: non vedono gli altri sistemi.

## Le tre difese (dal 08/10/2026)

### 1. La build di produzione si ferma

Se il sito ha le credenziali Kross e **non** ha una cache completa (le tre impostazioni della cache condivisa **oppure** le due dello store KV, con valori non vuoti), la build di **produzione** fallisce con un messaggio che dice cosa impostare. Le anteprime e lo sviluppo locale non sono toccati.

* Gira come passo `prebuild`, quindi **solo con il comando di build predefinito di Vercel** (`npm run build`). Se qualcuno lo sostituisce con `next build`, il controllo salta: non farlo.
* Si può provare a mano dal repository con `PREFLIGHT_FORCE=1 npm run prebuild`.
* La build controlla che le impostazioni **ci siano**, non che **funzionino**: per quello c'è il controllo di salute.

### 2. Il controllo di salute dice la verità

`GET https://<dominio del sito>/api/health` riporta il campo **`kross_token_cache`**:

| Valore | Significato | Status HTTP in produzione |
| - | - | - |
| `ok` | la cache è configurata e ha risposto a una **scrittura e rilettura vera** | 200 |
| `not_configured` | il sito usa Kross ma nessuna cache è configurata | **503** |
| `error` | la cache è configurata ma non funziona: segreto sbagliato, funzione assente, store irraggiungibile | **503** |
| `not_applicable` | il sito non usa Kross | 200 |

Cose da sapere per leggerlo:

* Il controllo della cache **non chiama mai KrossBooking**: scrive e rilegge una riga di prova dedicata, mai il token vero.
* Con la cache condivisa, la sola lettura non basta a dimostrare niente: con un segreto sbagliato la lettura risponde «vuoto», identica a «nessun token ancora». Per questo il controllo **scrive**: la scrittura è l'unica operazione che rifiuta esplicitamente un segreto sbagliato.
* Gli altri campi (`krossbooking`, `stripe`, …) non cambiano significato e **non** decidono lo status: un 503 dell'health oggi vuol dire «cache del token», non «Kross giù».
* L'header `x-health-kross-token-cache` riporta lo stesso valore.

### 3. Il log urla, una volta per istanza

A runtime ogni istanza scrive un **`console.error`** che inizia con **`[kross-token-cache]`** la prima volta che trova la cache assente, una chiamata alla cache fallita, o il segreto rifiutato. Nei log runtime di Vercel del progetto, filtra per quella stringa.

## L'avviso giornaliero

Ogni giorno alle 07:00 UTC la piattaforma Mattone **trova da sola** i siti di prenotazione diretta: guarda tutti i progetti del team su Vercel e tiene quelli attivi, con un deploy di produzione, che hanno le credenziali Kross del template fra le impostazioni. Per ognuno chiama l'health sul dominio di produzione (o sull'indirizzo Vercel del progetto `<progetto>.vercel.app`, se il dominio non risolve nel DNS) e, se un sito non risponde **200 con `kross_token_cache: "ok"`**, scrive nel canale Slack del team tecnico (**#mattone-coding**) un messaggio «Siti di prenotazione diretta: cache token Kross non a posto», con un punto per ogni sito e la diagnosi.

* **I siti nuovi vengono sorvegliati in automatico**: un sito creato dal template entra nel controllo dal primo deploy di produzione, senza aggiungerlo da nessuna parte.
* Un sito che usa Kross ma **non espone il campo** (fork vecchio, senza le difese di questa pagina) viene segnalato, come uno che **non risponde**.
* I progetti **in pausa** non vengono controllati.
* **Dominio che non risponde, sito sano**: un dominio può risolvere nel DNS e non servire il sito (agganciato a Vercel ma con il certificato non ancora pronto, o non più usato dallo studente). Se il dominio non dà nessuna risposta, l'avviso riprova sull'indirizzo `<progetto>.vercel.app`: se lì l'health è **200 con `ok`**, il sito è considerato **sano** (la cache funziona) e il dominio diventa solo una **nota informativa** nel riepilogo del controllo, mai un allarme da sola; compare in coda come ℹ️ solo se quel giorno parte un avviso per un altro sito. Se non risponde neanche l'indirizzo Vercel, arriva l'allarme con **entrambi** gli indirizzi. Un dominio che **risponde** con un errore (per esempio 503) resta un allarme: è il sito che risponde, non il dominio.
* Se la ricerca dei siti fallisce, arriva comunque un avviso «scoperta automatica FALLITA»: il silenzio vuol dire solo «tutti a posto».

Se tutti i siti sono a posto **non arriva niente**. Le sole eccezioni manuali (un sito fuori dal team Vercel da aggiungere, un progetto da escludere con il motivo) stanno nel codice della piattaforma.

## Cosa fare quando arriva l'avviso

<Steps>
  <Step title="Rileggi l'health a mano">Apri l'indirizzo dell'health indicato nel messaggio. Annota status HTTP e valore di `kross_token_cache`: l'avviso fotografa le 07:00, il sito potrebbe essere già cambiato.</Step>
  <Step title="«nessuna risposta»">Non hanno risposto né il dominio né l'indirizzo `<progetto>.vercel.app` (l'avviso li cita tutti e due): il sito è giù. Non è la cache: controlla l'ultimo deploy di produzione sul progetto Vercel. Se invece non risponde solo il dominio e l'indirizzo Vercel è sano, l'allarme non parte (resta la nota nel riepilogo): DNS e certificato del dominio si controllano su Vercel senza urgenza.</Step>
  <Step title="«senza campo kross_token_cache»">Il deploy in produzione è precedente alle difese di questa pagina (o l'health è rotto). Controlla che l'ultimo commit di `main` sia quello in produzione; se non lo è, verifica perché il deploy da `main` non è partito o non è finito.</Step>
  <Step title="not_configured">Mancano le impostazioni della cache in **Production** sul progetto Vercel. Impostale (`SUPABASE_URL` + `SUPABASE_ANON_KEY` + `GATEWAY_SHARED_SECRET` per i siti del team, `KV_REST_API_URL` + `KV_REST_API_TOKEN` da uno store collegato per i siti degli studenti), poi **rideploya da `main`**: le impostazioni valgono solo per i deploy nuovi. Mai `vercel deploy --prod` dal computer.</Step>
  <Step title="error">La cache c'è ma non risponde. Apri i log runtime del progetto e cerca `[kross-token-cache]`: il messaggio dice quale passo fallisce (segreto rifiutato, funzione assente, timeout, store KV). Il caso più comune è il **segreto copiato male** (`GATEWAY_SHARED_SECRET`): si reimposta il valore giusto e si rideploya.</Step>
  <Step title="Ricontrolla">Dopo il deploy, l'health deve tornare **200** con `ok`. Solo allora rispondi nel thread dell'avviso con cosa hai fatto.</Step>
</Steps>

<Warning>**Se il pool è già pieno** (`error_code 12` su ogni chiamata della struttura), sistemare la cache **ferma l'accumulo ma non svuota il pool**: le sessioni già aperte scadono da sole 7 giorni dopo l'ultimo uso. Non si può chiedere a Kross di alzare il tetto, e ritentare l'accesso a ripetizione peggiora le cose. Avvisa il team tecnico: va deciso come servire la struttura nel frattempo.</Warning>

## Checklist: sito nuovo dal template

Da seguire insieme alla [Procedura guidata](/integrazioni/direct-booking/procedura-guidata), fase 7.

1. Scegli la cache: **store KV del progetto** se il deploy è dello studente; **cache condivisa Mattone** solo se il sito lo opera il team.
2. Per lo store KV: Vercel → progetto → **Storage** → crea e **collega** lo store, così le impostazioni arrivano da sole. Per la cache condivisa: le tre impostazioni le configura il team, mai incollate in chat.
3. Imposta tutto in **Production** (e in Preview, se le anteprime parlano con Kross), con il comando di build **predefinito**.
4. Deploy da `main`. Se la build si ferma con «NO Kross token cache», manca il punto 2: non aggirarla.
5. Apri `/api/health` sul dominio vero: **200** e `kross_token_cache: "ok"`.
6. Non serve aggiungere il sito da nessuna parte: l'avviso giornaliero lo trova da solo. Il giorno dopo, verifica che **non** l'abbia segnalato.

<CardGroup cols={2}>
  <Card title="Direct Booking: come si crea" icon="arrow-up-right-from-square" href="/integrazioni/direct-booking/panoramica">Stack, template, vincoli</Card>
  <Card title="Kross: rate limit e trappole" icon="arrow-up-right-from-square" href="/integrazioni/kross/rate-limit-trappole">I limiti per struttura</Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.