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

# Multi-Tenancy e Isolamento dei Workspace

> Come Switchbord applica un rigoroso isolamento dei dati tra le organizzazioni tenant, impedendo l'accesso ai dati tra workspace diversi a ogni livello.

## Modello di Isolamento

Switchbord è una piattaforma multi-tenant in cui ogni organizzazione tenant opera come un **workspace** indipendente. La garanzia di isolamento è la seguente:

> Un utente nel workspace A non può leggere, scrivere o agire sui dati appartenenti al workspace B — indipendentemente da come vengono costruite le chiamate API.

Questa garanzia è applicata lato server a livello di API, non tramite routing lato client o controlli dell'interfaccia utente da soli.

## Risoluzione del Contesto del Workspace

### `resolveCallerWorkspaceFromSupabase(userId)`

Ogni route API autenticata risolve il contesto del workspace interrogando la tabella `workspace_members` con l'ID dell'utente autenticato:

```typescript theme={null}
// Solo lato server — non legge mai variabili d'ambiente o header del client
async function resolveCallerWorkspaceFromSupabase(userId: string) {
  const { data, error } = await supabase
    .from('workspace_members')
    .select('workspace_id, role')
    .eq('user_id', userId)
    .single();

  if (error || !data) throw new UnauthorizedError();
  return { workspaceId: data.workspace_id, role: data.role };
}
```

Proprietà principali:

* Legge da `workspace_members`, non da variabili d'ambiente
* Restituisce il workspace a cui l'utente appartiene effettivamente — non può essere sovrascritto dai parametri della richiesta
* Genera immediatamente un'eccezione se l'utente non è membro di alcun workspace
* Utilizzata come fondamento per tutti gli accessi ai dati con ambito workspace

### `requireSettingsAccess()`

Tutte le 13 route API delle impostazioni utilizzano `requireSettingsAccess()` come prima operazione, che chiama `resolveCallerWorkspaceFromSupabase` e applica un livello di ruolo minimo prima che qualsiasi dato delle impostazioni venga letto o scritto:

```typescript theme={null}
const { workspaceId, role } = await requireSettingsAccess(req, ['owner', 'admin']);
// workspaceId è ora considerato attendibile — usarlo per tutte le query successive
```

<Warning>
  Non passare mai `workspaceId` come parametro di query o campo del corpo della richiesta utilizzato per l'autorizzazione. Derivarlo sempre lato server dalla sessione autenticata.
</Warning>

## Pattern Deprecato: `readSingleWorkspace()`

La funzione `readSingleWorkspace()` leggeva la configurazione del workspace da variabili d'ambiente, il che è incompatibile con la multi-tenancy. È stata **deprecata e rimossa** da tutti i percorsi di codice di produzione.

Percorso di migrazione per qualsiasi codice che la referenzia ancora:

```typescript theme={null}
// DEPRECATA — non utilizzare
const workspace = await readSingleWorkspace();

// CORRETTA — risolvere dall'utente autenticato
const { workspaceId } = await resolveCallerWorkspaceFromSupabase(userId);
const workspace = await getWorkspaceById(workspaceId);
```

## Threading delle Route delle Impostazioni

Tutte le 13 route API delle impostazioni fanno passare (thread) il `workspaceId` derivato da `requireSettingsAccess()` attraverso ogni query a valle. Nessuna route delle impostazioni legge dati del workspace senza prima stabilire il contesto del workspace del chiamante.

Esempio di pattern per una route delle impostazioni:

```typescript theme={null}
export async function GET(req: NextRequest) {
  const { workspaceId, role } = await requireSettingsAccess(req, ['owner', 'admin', 'developer']);

  const settings = await db
    .select()
    .from(workspaceSettings)
    .where(eq(workspaceSettings.workspaceId, workspaceId))  // sempre con ambito definito
    .limit(1);

  return Response.json(settings);
}
```

## Isolamento del Dispatch dei Messaggi

La funzione `dispatchMessageViaMetaInSupabase` legge le credenziali Meta dal workspace identificato da `job.workspace_id` — il workspace che possiede il job, non una configurazione globale:

```typescript theme={null}
async function dispatchMessageViaMetaInSupabase(job: MessageJob) {
  // Credenziali recuperate dal workspace che possiede questo job
  const credentials = await getWorkspaceMetaCredentials(job.workspace_id);
  // i job del workspace A usano sempre il token Meta del workspace A
  return sendViaMetaAPI(credentials, job.payload);
}
```

Ciò significa che:

* Il Workspace A non può causare l'invio di messaggi tramite il numero di telefono Meta del Workspace B
* La fuoriuscita di credenziali tra tenant a livello di dispatch è strutturalmente impossibile
* Ogni workspace configura e ruota il proprio token di accesso Meta in modo indipendente

## Modello di Adesione Solo su Invito

Gli utenti possono aderire a un workspace solo tramite un invito esplicito da parte di un admin o owner esistente del workspace. Non esiste alcun flusso di scoperta o adesione self-service. Ciò garantisce che:

* L'appartenenza al workspace sia sempre intenzionale
* I nuovi membri ricevano solo il ruolo esplicitamente concesso dall'admin che invita
* La rimozione di un membro revochi immediatamente tutti gli accessi, incluse le sessioni attive

Vedi [Autenticazione e Controllo degli Accessi](/it/security/authentication) per i dettagli sulla revoca delle sessioni.

## Ambito delle API Key

Le API key hanno ambito limitato al workspace che le ha create. Tutte le operazioni sulle API key (elenco, eliminazione, revoca) filtrano in base al `workspace_id` risolto del chiamante:

```typescript theme={null}
// Eliminazione di una API key — sempre con ambito limitato al workspace del chiamante
await db.delete(apiKeys)
  .where(
    and(
      eq(apiKeys.id, keyId),
      eq(apiKeys.workspaceId, workspaceId)  // non è possibile eliminare chiavi di altri workspace
    )
  );
```

## Isolamento dell'Assistente AI

L'endpoint `/api/ai-assistant` in precedenza non disponeva di un auth guard. Ora richiede l'autenticazione e risolve il contesto del workspace prima di elaborare qualsiasi richiesta. Il contesto AI ha ambito limitato ai contatti e alle conversazioni all'interno del solo workspace del chiamante.

## Mappatura della Conformità

| Standard  | Controllo                                                                           | Implementazione                                                                                                 |
| --------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| ISO 27001 | A.9.1 — Politica di controllo degli accessi                                         | Accesso con ambito workspace applicato a livello di API                                                         |
| ISO 27001 | A.9.4 — Controllo dell'accesso al sistema e alle applicazioni                       | `requireSettingsAccess()` su tutte le route delle impostazioni                                                  |
| GDPR      | Art.25 — Protezione dei dati fin dalla progettazione e per impostazione predefinita | Isolamento del workspace per impostazione predefinita; nessuna fuoriuscita di dati tra tenant per progettazione |
| GDPR      | Art.32 — Sicurezza del trattamento                                                  | Misure tecniche che impediscono l'accesso non autorizzato tra workspace                                         |
| SOC 2     | CC6.1 — Controlli di accesso logico e fisico                                        | Appartenenza al workspace applicata lato server                                                                 |
| SOC 2     | CC6.2 — Prima dell'emissione delle credenziali di sistema                           | Modello solo su invito; credenziali emesse solo con azione esplicita dell'admin                                 |

<Tip>
  Per la mappatura completa dei controlli di conformità, vedi la [Matrice di Conformità](/it/security/compliance-matrix).
</Tip>
