docs: document full and embedded rendering with server authentication

This commit is contained in:
Codex
2026-09-13 17:28:10 +02:00
parent 26c5605ff7
commit 9051463654
24 changed files with 789 additions and 25 deletions
+130
View File
@@ -0,0 +1,130 @@
# Rendering full ed embedded
ThothII ha una sola applicazione React, una sola build Vite e gli stessi servizi
backend. «Doppio rendering» significa due modi di ospitare quella applicazione,
non due versioni delle pagine e non rendering React sul server. Django renderizza
il contenitore Omics; React renderizza ThothII nel browser, dentro `#root`.
## Tre decisioni indipendenti
| Decisione | Configurazione | Effetto |
| --- | --- | --- |
| Distribuzione | `profile: local` oppure `server` | Compose, percorsi e vincoli operativi |
| Presentazione | `shell.mode: full` oppure `embedded` | Proprietario di header e preferenze |
| Autenticazione | `auth.yaml` local/OIDC oppure `AUTH_MODE=upstream` | Chi verifica l'identità, come arriva al backend |
Il Mac usa **full + local**, con lingua iniziale inglese. L'integrazione Omics
usa **embedded + upstream**, con accesso già verificato dal portale. Un server
autonomo può usare **full + oidc**. Cambiare `shell.mode` non abilita un metodo
di autenticazione e non modifica permessi o proprietari delle sessioni.
Full con upstream può visualizzare un'identità già verificata dal proxy, ma non
ha un logout ThothII disponibile: non è il profilo autonomo con login/logout.
Embedded non avvia login locale o OIDC anche se il backend è configurato così;
questa combinazione non realizza il login unico Omics e non va usata come fallback.
## Composizione comune
```mermaid
flowchart TD
CONFIG["config.js pubblico"] --> SHELL["ShellProvider"]
FULL["Preferenze full nel browser"] --> SHELL
HOST["Documento Omics"] --> ADAPTER["OmicsPortalAdapter: solo presentazione"]
ADAPTER --> SHELL
SHELL --> GATE["AuthGate: verifica GET /me"]
GATE --> APP["AppShell: stesse pagine, sessioni e amministrazione"]
AUTH["Backend: cookie locale/OIDC o identità upstream"] --> GATE
```
`ShellProvider` risolve la configurazione, applica lingua/tema e monta i contenuti
solo dopo uno snapshot host valido in embedded. `AuthGate` verifica l'accesso;
`AppShell` e le pagine non devono leggere selettori o eventi specifici di Omics.
Il cambio utente smonta lo stato applicativo della precedente identità.
## Full
- Header ThothII rosso Omics `#CB333B` in entrambi i temi; logo interamente chiaro.
- Selettore EN/IT, tema light/dark, fullscreen e nome verificato dell'utente.
- Menu del nome con logout soltanto per local/OIDC; nessuna rotellina admin.
L'amministrazione resta nella navigazione applicativa, secondo i permessi.
- Margine sinistro vuoto e simmetrico al destro: `max(20px, 1.5rem)`, normalmente
24px con radice a 16px. Non è una seconda sidebar di navigazione.
- Lingua e tema ricordati sullo stesso origin in `localStorage`, nelle chiavi
`thothii:shell:locale` e `thothii:shell:theme`. Non sono preferenze server per
utente. In assenza di preferenze: `defaultLocale` e tema light.
- Fullscreen usa `document.documentElement.requestFullscreen()` e
`document.exitFullscreen()`: nasconde il contorno del browser dove supportato.
L'icona cambia sullo stato reale, anche dopo Esc; un rifiuto mostra un errore.
Non è un semplice ingrandimento CSS e non scatta automaticamente all'accesso.
## Embedded
- Nessun header ThothII, selettore lingua, toggle tema, login o logout autonomo.
I controlli rimangono nell'header generale Omics.
- React è nello stesso documento della pagina `/kokoro/datamart-builder/`, non
in un iframe. Non serve `postMessage` né un secondo protocollo di sessione.
- L'adapter legge la lingua Django già confermata, osserva il tema del documento
e ascolta il fullscreen reale. Le azioni rimangono di proprietà del portale.
- Un contesto Omics mancante o invalido mostra un errore d'integrazione; non
passa silenziosamente a full e non offre un secondo login.
- Il portale assegna l'altezza disponibile sotto il proprio header: catena flex
con `min-height: 0`, root contenuto e altezza applicativa vincolata al contenitore.
Il contratto ThothII espone `--thoth-app-height` (fallback `100dvh`); verificare
il contenitore reale, non presumere che l'intera viewport appartenga a React.
Il template Omics mantiene inoltre i suoi override di compatibilità.
Il reset CSS è limitato al mount React e ai popup dell'applicazione, senza
richiedere CSS `@scope`. I token e i popup seguono il tema applicativo. Questo
non rende indipendenti fogli di stile arbitrari caricati dal portale: la verifica
del documento condiviso rimane necessaria a ogni integrazione.
## Caricamento e configurazione pubblica
Il descrittore installato è la sorgente di verità. Il CLI genera
`generated/frontend/config.js` e il suo mount di sola lettura nella proiezione
`generated/compose.models.yaml`. Il file pubblico contiene solo `backendBaseUrl`
e `shell`, mai identità, token, password o percorsi host. Va caricato **prima** del
modulo React e servito senza cache. Nessuna build separata è richiesta per
cambiare modalità; occorre rigenerare e applicare i mount tramite il lifecycle.
L'ordine Omics è: config pubblico → override del solo prefisso API → asset dal
manifest Vite. L'override deve conservare `shell`; l'adapter non configura il proxy.
Il default completo di shell omessa è embedded/en/omics-portal. Il CLI normalizza
anche singoli campi omessi; un oggetto `shell` scritto manualmente nel browser
deve invece contenere `mode` e `defaultLocale`, altrimenti viene rifiutato.
## Lingua, continuità e dati
La lingua UI traduce il testo dell'applicazione, non i contenuti di dominio.
Alla creazione, la lingua UI viene acquisita come `interactionLanguage`; il
manifest salva `interaction_language`, che governa domande e scelte del modello.
Alla ripresa vale la lingua salvata, non l'ultima scelta dell'header. Per i manifest
precedenti senza campo viene fissata la lingua workspace disponibile alla prima ripresa.
Il cambio lingua Omics invia il form Django e ricarica la pagina. ThothII conserva
solo l'ID della selezione in `sessionStorage`, separato per pathname, issuer e
subject. Riapre i documenti, non avvia una generazione. Bozze non inviate e modifiche
non salvate richiedono conferma prima della navigazione; non sono una trascrizione
salvata. La ripresa operativa resta esplicita.
## Punti di implementazione e manutenzione
| Sorgente | Responsabilità |
| --- | --- |
| `tools/tht/internal/config/shell.go` | Normalizzazione e validazione del descrittore |
| `tools/tht/internal/modelprojection/projection.go` | Config pubblico e mount generati |
| `frontend/src/api/runtime-config.ts` | Validazione browser e prefisso API same-origin |
| `frontend/src/shell/host/ShellProvider.tsx` | Composizione, preferenze e tema |
| `frontend/src/shell/host/FullHeader.tsx` | Controlli solo full |
| `frontend/src/shell/host/OmicsPortalAdapter.ts` | Conoscenza del documento Omics |
| `frontend/src/auth/AuthGate.tsx` | Accesso e ricontrolli al ritorno alla pagina |
| `backend/src/auth/auth.ts` e `principal.ts` | Verifica server dell'identità |
Per un altro portale servono un'implementazione del
[PortalAdapter](../contracts/portal-shell-adapter-v1.md), la sua registrazione nei
validatori CLI/browser e nel punto di composizione, oltre al
[contratto di autenticazione server](../install/authentication-upstream.md).
Il nome di una classe non è un plugin caricabile dinamicamente da YAML.
Procedure: [configurazione e deploy](../operations/shell-and-localization.md),
[autenticazione](authentication.md), [accettazione](../testing/authentication-manual-acceptance.md).