Add full shell, replaceable Omics adapter and bilingual interaction
Implement approved specification #32 and tickets #33-#37. Keep host authentication server-verified and pin session interaction language. Compile scoped base selectors for browser compatibility and retain full gutters during CSS pruning.
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# ADR 0021 — Shell separati e adapter sostituibile per il portale
|
||||
|
||||
- Stato: accettato
|
||||
- Data: 2026-09-13
|
||||
|
||||
## Decisione
|
||||
|
||||
ThothII espone due modalità di installazione, selezionate da `shell.mode`:
|
||||
|
||||
- `embedded` (default): ThothII è ospitato da Omics Portal. Non renderizza alcun header e
|
||||
riceve dal portale lingua, tema e fullscreen. L'accesso resta verificato dal server.
|
||||
- `full`: ThothII è autonomo. Renderizza il proprio header, con selettore lingua, tema,
|
||||
fullscreen e nome utente. Il click sul nome apre il logout. Non mostra mai la rotellina o
|
||||
altri comandi amministrativi del portale. Mantiene un rail vuoto a sinistra di almeno 20 px.
|
||||
|
||||
Il fatto che la shell sia `full` è distinto dallo stato `fullscreen`: la prima decide quale
|
||||
contenitore viene renderizzato, il secondo indica se è attiva la Fullscreen API del browser.
|
||||
L'icona passa da “entra in fullscreen” a “torna alla modalità normale”; anche `Esc` aggiorna lo
|
||||
stato visualizzato.
|
||||
|
||||
La configurazione installata resta semplice e retrocompatibile. Sul Mac di sviluppo il profilo
|
||||
locale userà:
|
||||
|
||||
```yaml
|
||||
shell:
|
||||
mode: full
|
||||
defaultLocale: en
|
||||
```
|
||||
|
||||
Il deploy sul server userà invece:
|
||||
|
||||
```yaml
|
||||
shell:
|
||||
mode: embedded
|
||||
adapter: omics-portal
|
||||
```
|
||||
|
||||
`defaultLocale` indica la lingua iniziale della shell full; in embedded la fonte autorevole resta
|
||||
il portale.
|
||||
|
||||
L'adapter è l'unico confine tra ThothII e il portale. La sua interfaccia pubblica è volutamente
|
||||
profonda e minima: consegna solo snapshot dello stato, senza esporre comandi, token, identità o
|
||||
dettagli di trasporto.
|
||||
|
||||
```ts
|
||||
export type HostShellState = {
|
||||
locale: string; // BCP-47, inizialmente it/en
|
||||
theme: "light" | "dark";
|
||||
fullscreen: boolean;
|
||||
};
|
||||
|
||||
export interface PortalAdapter {
|
||||
subscribe(
|
||||
onState: (state: HostShellState) => void,
|
||||
onError: (error: Error) => void,
|
||||
): () => void;
|
||||
}
|
||||
```
|
||||
|
||||
`OmicsPortalAdapter` è l'implementazione corrente. Un adapter per un altro portale potrà
|
||||
sostituirlo senza modificare shell, i18n o workflow. In `full` l'adapter non viene istanziato:
|
||||
lo stato è gestito internamente dalla shell.
|
||||
|
||||
Per l'integrazione oggi operativa, che monta la SPA direttamente nel DOM di Omics Portal,
|
||||
l'adapter legge la lingua effettiva dal selettore Omics, osserva l'attributo del tema e ascolta
|
||||
il fullscreen del documento. Selettori e osservatori restano privati dell'implementazione Omics.
|
||||
La lingua segue il normale ricaricamento Django; tema e fullscreen cambiano nella pagina aperta.
|
||||
La revisione approvata del 2026-09-13 elimina il precedente handshake a eventi: non servono
|
||||
messaggi personalizzati, versioni di trasporto o timeout di avvio. Un futuro adapter potrà usare
|
||||
un diverso trasporto senza modificare l'interfaccia applicativa.
|
||||
|
||||
Se `shell` o l'adapter embedded sono omessi, si usa `embedded` con `omics-portal`. Questo default
|
||||
supporta il documento Omics esistente; nomi adapter sconosciuti o dati host mancanti producono
|
||||
un errore esplicito, senza attivare la shell full.
|
||||
|
||||
## Confini che restano invariati
|
||||
|
||||
L'identità e l'autorizzazione del backend non vengono ricostruite nel browser. In embedded,
|
||||
Omics Portal continua a gestire login e logout e la catena server-side `auth_request` continua a
|
||||
fornire i principal header già previsti. Lo stato UI non dichiara l'utente autenticato: il modulo
|
||||
di accesso usa la verifica backend esistente anche alla riconnessione e al ritorno alla pagina.
|
||||
Un rifiuto su una singola operazione non equivale automaticamente alla perdita dell'accesso.
|
||||
|
||||
La lingua UI e la lingua di interazione con il modello restano separate dalla lingua del
|
||||
workspace; il relativo contratto è in [ADR 0022](0022-separate-ui-locale-from-session-interaction-language.md).
|
||||
|
||||
## Alternative scartate
|
||||
|
||||
- Duplicare l'header di Omics in embedded: crea due fonti di stato e incompatibilità visive.
|
||||
- Spargere controlli `if embedded/full` nei componenti: lega ogni pagina al portale.
|
||||
- Trasmettere utente o token nel bridge: aumenta superficie e accoppia UI e autenticazione.
|
||||
- Introdurre un protocollo completo request/response: non aggiunge funzionalità richiesta.
|
||||
- Usare `profile` per distinguere le shell: `profile` descrive la topologia dell'installazione,
|
||||
non la sua presentazione.
|
||||
|
||||
## Conseguenze
|
||||
|
||||
La soluzione richiede un adapter nel frontend che osserva il documento condiviso e mantiene la
|
||||
logica di shell locale a ThothII. Il backend non necessita di un nuovo protocollo di autenticazione
|
||||
o di una nuova sessione browser. Un nuovo portale deve soddisfare anche il contratto server di
|
||||
identità fidata: la sola sostituzione della classe UI non sostituisce quel contratto.
|
||||
@@ -0,0 +1,51 @@
|
||||
# Separate UI locale from session interaction language
|
||||
|
||||
status: accepted
|
||||
|
||||
ThothII distinguishes three language concepts:
|
||||
|
||||
- `workspace.language` remains the language of workspace-owned documents, descriptions and Evidence;
|
||||
- `ui_locale` controls deterministic ThothII chrome such as labels, form help, placeholders, errors,
|
||||
accessibility text and review-widget chrome;
|
||||
- `interaction_language` is persisted in a session and controls model-generated questions,
|
||||
explanations and reviewer proposals.
|
||||
|
||||
The initial locale catalog supports Italian and English and uses extensible BCP-47 language tags.
|
||||
Missing deterministic translations fall back to English. The selected UI locale supplies the default
|
||||
interaction language when a new session is created. A resumed session always uses its persisted
|
||||
interaction language; changing the host or full-shell UI locale must not silently rewrite an existing
|
||||
session or make its model output switch language mid-workflow.
|
||||
|
||||
The distinction is required because the current workspace contract already uses `language` for
|
||||
content and the PSD workspace is Italian. Reusing that field for a browser preference would make a
|
||||
visual choice mutate domain content semantics. The model receives the session interaction language
|
||||
through the session/Pi workflow context. SQL, identifiers, database values and other technical
|
||||
artifacts remain governed by their existing contracts and are not translated as UI strings.
|
||||
|
||||
In `full`, the local shell owns `ui_locale` and supplies it when starting a new session. In
|
||||
`embedded`, the host adapter is authoritative for `ui_locale`; ThothII applies host changes to
|
||||
deterministic UI immediately while preserving the interaction language of any active session.
|
||||
|
||||
We considered using only `workspace.language`, using only a global browser locale, and translating
|
||||
the model output after generation. The first conflates domain content with UI preference; the second
|
||||
cannot preserve a session's language or follow the host portal; and the third would be unsafe for
|
||||
structured reviewer decisions and would not control the model's reasoning or proposal language.
|
||||
|
||||
## Considered Options
|
||||
|
||||
- One mutable `language` field for workspace, UI and session was rejected because the fields have
|
||||
different owners and lifecycles.
|
||||
- Client-only translation of reviewer choices was rejected because choices can be generated by the
|
||||
model and must be requested in the intended language.
|
||||
- An English-only deterministic chrome was rejected because embedded and full installations must
|
||||
follow the selected host/user language.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Session creation and the persisted manifest gain an explicit interaction-language value.
|
||||
- Legacy manifests without that value use the workspace language, pinned idempotently on first
|
||||
resume; the browser locale must not determine this compatibility value.
|
||||
- Resume must read that value from the manifest and must not accept a new locale as an override.
|
||||
- The workflow prompt contract and deterministic reviewer-widget builders need a locale-aware input.
|
||||
- Frontend strings need a catalog and stable keys; backend events should expose stable codes where
|
||||
the frontend is responsible for localization.
|
||||
@@ -0,0 +1,110 @@
|
||||
# Portal Shell Adapter v1
|
||||
|
||||
Contratto minimo della presentazione embedded. La revisione approvata il 2026-09-13
|
||||
sostituisce il precedente trasporto a eventi personalizzati con l'osservazione del
|
||||
documento condiviso. Non trasferisce identità, token o stato di autenticazione.
|
||||
|
||||
## Configurazione
|
||||
|
||||
Sul Mac:
|
||||
|
||||
```yaml
|
||||
shell:
|
||||
mode: full
|
||||
defaultLocale: en
|
||||
```
|
||||
|
||||
Sul server Omics:
|
||||
|
||||
```yaml
|
||||
shell:
|
||||
mode: embedded
|
||||
adapter: omics-portal
|
||||
```
|
||||
|
||||
Se `shell` o `mode` sono omessi, la modalità è embedded. L'adapter embedded
|
||||
predefinito è `omics-portal`; un nome sconosciuto è un errore di configurazione.
|
||||
Full non istanzia adapter. `defaultLocale` inizializza full; in embedded il locale
|
||||
proviene dal portale. L'autenticazione si configura separatamente dalla shell.
|
||||
|
||||
## API applicativa
|
||||
|
||||
```ts
|
||||
export type PortalSnapshot = {
|
||||
locale: string;
|
||||
theme: "light" | "dark";
|
||||
fullscreen: boolean;
|
||||
};
|
||||
|
||||
export interface PortalAdapter {
|
||||
subscribe(
|
||||
onState: (state: PortalSnapshot) => void,
|
||||
onError: (error: Error) => void,
|
||||
): () => void;
|
||||
}
|
||||
```
|
||||
|
||||
Una sottoscrizione installa gli osservatori e consegna lo snapshot iniziale senza
|
||||
richiedere messaggi all'altro applicativo. Gli aggiornamenti contengono snapshot
|
||||
completi e validati. La disiscrizione elimina tutti i listener e osservatori.
|
||||
La lingua viene risolta tramite i cataloghi UI, con fallback inglese.
|
||||
|
||||
## Implementazione Omics
|
||||
|
||||
L'integrazione monta React nel documento Django, non in un iframe.
|
||||
|
||||
| Dato | Fonte privata dell'adapter | Aggiornamento |
|
||||
| --- | --- | --- |
|
||||
| Locale | `data-lang` del selettore `.omics-language-select` | nuova pagina Django dopo `set_language` |
|
||||
| Tema | `data-bs-theme` su `html` | osservazione limitata a quell'attributo |
|
||||
| Fullscreen | stato effettivo del documento | evento del browser, inclusa uscita con Esc |
|
||||
|
||||
L'attributo `lang` storicamente fisso a `en` nel template base non deve essere
|
||||
usato come surrogato della lingua selezionata. Leggere il valore renderizzato dal
|
||||
server evita anche di anticipare un cambio lingua prima che il form abbia successo.
|
||||
|
||||
L'assenza del contesto host atteso produce un errore di integrazione; non abilita
|
||||
controlli locali. Non si introducono eventi `ready/state`, handshake, timeout,
|
||||
versioni dei messaggi o comandi duplicati. Selettori e dettagli Omics non devono
|
||||
essere letti dai componenti applicativi.
|
||||
|
||||
## Proprietà per modalità
|
||||
|
||||
| Funzione | Full | Embedded |
|
||||
| --- | --- | --- |
|
||||
| Header | ThothII | solo Omics |
|
||||
| Lingua | selettore locale | selettore Omics, normale reload Django |
|
||||
| Tema | toggle locale light/dark | stato Omics |
|
||||
| Fullscreen | controllo locale, stato reale | controllo Omics, stato reale |
|
||||
| Login/logout | autenticazione ThothII configurata | autenticazione Omics esistente |
|
||||
| Nome utente | header ThothII | header Omics |
|
||||
| Rotellina amministrativa | mai | eventuale comando del portale |
|
||||
|
||||
## Accesso e continuità
|
||||
|
||||
Il server Omics verifica l'accesso a Datamart Builder e il proxy trasmette i
|
||||
principal header normalizzati al backend ThothII. La UI usa `/me`; non effettua
|
||||
un secondo login. Un altro portale deve soddisfare anche questo contratto server,
|
||||
oltre a fornire una nuova implementazione dell'adapter UI.
|
||||
|
||||
Il logout del portale segue la sua navigazione. Una perdita di accesso rilevata
|
||||
dal server chiude lo stato protetto; un 403 di una singola operazione non equivale
|
||||
automaticamente a logout. La riconnessione degli eventi e il ritorno alla pagina
|
||||
ricontrollano l'accesso. Non si garantisce revoca istantanea di una connessione
|
||||
aperta in un'altra scheda attraverso il solo controllo iniziale del proxy.
|
||||
|
||||
Il cambio lingua può ricaricare la pagina: conservare la selezione della sessione,
|
||||
proteggere le modifiche non salvate e non avviare una nuova generazione al reload.
|
||||
Non si conserva una trascrizione integrale nel browser. La lingua della sessione
|
||||
rimane quella registrata nel manifest, secondo ADR 0022.
|
||||
|
||||
## Sostituzione e verifiche
|
||||
|
||||
Un nuovo adapter può usare un diverso documento o trasporto, ma deve rispettare
|
||||
la stessa sottoscrizione e mantenere la conoscenza del portale nella propria
|
||||
implementazione. Non occorre implementare ora iframe o un secondo portale.
|
||||
|
||||
Verificare snapshot prima/dopo il montaggio, tema, fullscreen con Esc, cleanup,
|
||||
contesto host mancante, assenza di header ThothII embedded, accesso singolo,
|
||||
locale dopo reload e compatibilità del prefisso API. Full deve funzionare senza
|
||||
alcun elemento Omics presente.
|
||||
@@ -0,0 +1,186 @@
|
||||
# Shell, autenticazione e lingue
|
||||
|
||||
Questa guida accompagna la [specifica approvata](../plans/2026-09-13-full-shell-spec.md)
|
||||
e il [contratto Portal Shell Adapter](../contracts/portal-shell-adapter-v1.md).
|
||||
|
||||
## Scegliere il contenitore
|
||||
|
||||
La modalità della shell è indipendente dal profilo di distribuzione e dal metodo
|
||||
di autenticazione. Un server può ospitare full; un ambiente locale può ospitare
|
||||
embedded per provare un'integrazione.
|
||||
|
||||
Per questo Mac, nel descrittore installato:
|
||||
|
||||
```yaml
|
||||
shell:
|
||||
mode: full
|
||||
defaultLocale: en
|
||||
```
|
||||
|
||||
Per il server Omics:
|
||||
|
||||
```yaml
|
||||
shell:
|
||||
mode: embedded
|
||||
adapter: omics-portal
|
||||
```
|
||||
|
||||
L'assenza di `shell` conserva embedded con adapter Omics. Un nome adapter
|
||||
sconosciuto è un errore, non una richiesta di fallback a full. Full ignora
|
||||
l'adapter Omics riconosciuto e non lo istanzia. Un locale ben formato per cui non
|
||||
esiste ancora un catalogo usa l'inglese nell'interfaccia.
|
||||
|
||||
`defaultLocale` è il valore iniziale, non un vincolo che annulla ogni scelta
|
||||
dell'utente. Full ricorda lingua e tema nel browser; embedded segue soltanto
|
||||
Omics. Le preferenze non modificano il descrittore installato.
|
||||
|
||||
## Applicare una modifica all'installazione
|
||||
|
||||
Aggiornare prima il binario nativo `tht`: le versioni precedenti rifiutano la
|
||||
sezione `shell`. Modificare poi il descrittore e generare le proiezioni:
|
||||
|
||||
```bash
|
||||
tht --installation /percorso/assoluto/thothii-installation.yaml installation generate
|
||||
```
|
||||
|
||||
Il comando non avvia né arresta servizi. Genera anche
|
||||
`generated/frontend/config.js`, che contiene configurazione pubblica, e il
|
||||
relativo mount Compose. Non modificare a mano i file generati. `tht start`
|
||||
rigenera le proiezioni nel normale percorso di avvio.
|
||||
|
||||
Applicare il normale processo di aggiornamento dei container dell'installazione.
|
||||
Se si usa un launcher Compose personalizzato, deve includere la proiezione
|
||||
Compose generata e ricreare il frontend quando cambia la configurazione. Il
|
||||
fingerprint della configurazione pubblica permette a Compose di rilevare il cambio.
|
||||
La stessa immagine frontend supporta entrambe le modalità.
|
||||
|
||||
Controllare il `config.js` effettivamente servito, che non deve essere memorizzato
|
||||
in cache. In full la route API ordinaria è `/api`; Omics imposta nel template il
|
||||
prefisso same-origin `/datamart-builder/api`, mantenendo le altre impostazioni.
|
||||
|
||||
## Accesso in parole semplici
|
||||
|
||||
In Omics l'utente effettua l'accesso al portale come oggi. Quando sceglie
|
||||
Datamart Builder, il server controlla che possa usarlo e comunica a ThothII chi è.
|
||||
ThothII apre l'applicazione per quella persona: non presenta un altro login e non
|
||||
crea una seconda sessione browser. Le password non vengono trasmesse a ThothII.
|
||||
Il nome e il comando Esci rimangono nell'header del portale.
|
||||
|
||||
Sul Mac full, ThothII presenta il proprio login locale. Dopo l'accesso mostra il
|
||||
nome nell'header; il menu del nome contiene il logout. Riutilizza gli utenti e
|
||||
la configurazione di accesso dell'installazione. Full supporta anche un'eventuale
|
||||
autenticazione OIDC configurata; il suo logout termina la sessione ThothII, non
|
||||
promette di disconnettere l'utente da tutti gli altri servizi OIDC.
|
||||
|
||||
I controlli server restano autorevoli. Un errore su una singola operazione non
|
||||
deve cancellare automaticamente l'accesso all'intera applicazione. Un rifiuto
|
||||
della verifica dell'utente chiude invece lo stato protetto. L'accesso viene
|
||||
ricontrollato anche al ritorno alla pagina e quando il collegamento eventi deve
|
||||
riconnettersi. Questo non equivale a una revoca istantanea di ogni connessione
|
||||
già aperta in altre schede.
|
||||
|
||||
## Contratto server Omics
|
||||
|
||||
Il percorso corrente usa il controllo Django della capability
|
||||
`datamart_builder.access`, la subrequest nginx `auth_request` e gli header
|
||||
normalizzati `X-Thoth-Principal-Issuer`, `X-Thoth-Principal-Subject`,
|
||||
`X-Thoth-Principal-Display-Name` e `X-Thoth-Is-Admin`. Il browser non può
|
||||
scegliere queste identità: il proxy ricava gli header dal controllo server e
|
||||
sostituisce quelli eventualmente forniti dal client.
|
||||
|
||||
Mantenere il backend configurato per l'autenticazione upstream e i suoi controlli
|
||||
di autorizzazione. Non esporre un percorso alternativo che permetta al browser
|
||||
di raggiungerlo aggirando quel controllo. Non introdurre token nel documento,
|
||||
negli eventi UI o nella configurazione pubblica.
|
||||
|
||||
## Come funziona l'adapter
|
||||
|
||||
`OmicsPortalAdapter` è il solo modulo frontend che conosce il documento Omics.
|
||||
Legge il `data-lang` del selettore lingua, osserva `data-bs-theme` e ascolta lo
|
||||
stato fullscreen del documento. Fornisce snapshot `{ locale, theme, fullscreen }`
|
||||
al controller di shell. Non invia comandi al portale e non usa un handshake.
|
||||
|
||||
La pagina Omics deve continuare a esporre il selettore
|
||||
`select.omics-language-select` con la lingua renderizzata nel suo `data-lang`, e
|
||||
il tema light/dark nell'attributo di `html`. Il selettore lingua usa il normale
|
||||
form Django; non occorre convertirlo in una richiesta asincrona.
|
||||
|
||||
Per un altro portale, implementare la stessa sottoscrizione e selezionare il
|
||||
nuovo adapter nel punto di composizione. Le pagine, l'i18n e il workflow non
|
||||
devono acquisire riferimenti al nuovo portale. Sul lato server, il nuovo
|
||||
contenitore deve anche fornire un'identità verificata conforme al contratto
|
||||
upstream. Cambiare una classe JavaScript non sostituisce quel requisito.
|
||||
|
||||
## Lingue e sessioni
|
||||
|
||||
Ci sono tre scelte distinte:
|
||||
|
||||
| Scelta | Dove viene conservata | Cosa influenza |
|
||||
| --- | --- | --- |
|
||||
| Lingua UI | preferenza full o stato Omics | label, form, messaggi e controlli |
|
||||
| Lingua di interazione | `interaction_language` nel manifest | nuove domande, spiegazioni e scelte del modello |
|
||||
| Lingua workspace | configurazione del workspace | documenti, descrizioni e contenuti di dominio |
|
||||
|
||||
La creazione web acquisisce la lingua UI prima delle operazioni asincrone e la
|
||||
invia come `interactionLanguage`. Un cambio successivo non modifica quella
|
||||
richiesta. La ripresa legge il manifest e non usa il locale del browser come
|
||||
override. SQL, identificatori, valori e citazioni dei contenuti rimangono invariati.
|
||||
|
||||
Per sessioni precedenti senza `interaction_language`, la prima ripresa fissa la
|
||||
lingua del workspace in modo idempotente. Se il workspace era stato modificato
|
||||
nel frattempo, non esiste una registrazione da cui ricostruire con certezza la
|
||||
vecchia lingua: il criterio di compatibilità è quella disponibile alla ripresa.
|
||||
|
||||
Il cambio lingua di Omics ricarica la pagina. ThothII ricorda soltanto l'identificatore
|
||||
della sessione per utente e pagina, senza salvare una trascrizione nel browser.
|
||||
Il recupero riapre il pannello dei documenti; la ripresa operativa è esplicita e
|
||||
non avvia una generazione soltanto perché la pagina è stata ricaricata. Le bozze
|
||||
non inviate e le modifiche amministrative richiedono protezione dalla navigazione.
|
||||
|
||||
## Aggiungere e verificare traduzioni
|
||||
|
||||
I messaggi inglesi fungono da identificatori gettext-style e fallback. I
|
||||
cataloghi italiani sono divisi per area per agevolarne la manutenzione. Usare
|
||||
`useI18n()` nei componenti e interpolazioni nominate, evitando concatenazioni
|
||||
che rendano impossibile cambiare l'ordine delle parole. Non chiamare il traduttore
|
||||
su SQL, testi del modello o descrizioni del workspace.
|
||||
|
||||
Per una nuova lingua aggiungere il catalogo, registrarlo nel risolutore e renderlo
|
||||
disponibile nel selettore full. Il portale deve fornire il relativo locale. La
|
||||
lingua delle sessioni è già esplicita e non richiede una nuova struttura del manifest.
|
||||
Le traduzioni dei controlli della griglia provengono dal catalogo ufficiale della
|
||||
stessa versione di AG Grid.
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run check:i18n
|
||||
npx tsc -b
|
||||
npx vitest run
|
||||
```
|
||||
|
||||
Il controllo dei cataloghi segnala messaggi statici mancanti, interpolazioni
|
||||
incompatibili e traduzioni discordanti. Non può provare da solo la copertura di
|
||||
tutti i messaggi dinamici: completarlo con i test delle pagine e la verifica visiva.
|
||||
|
||||
La build verifica anche il CSS effettivamente generato: il reset Tailwind viene
|
||||
limitato al mount React e ai suoi popup con selettori ordinari, senza richiedere
|
||||
supporto browser a `@scope`. Mantenere letterali le classi dei due modi della shell
|
||||
per conservarle durante la rimozione del CSS inutilizzato. Le griglie usano il tema
|
||||
CSS esistente con i token light/dark; non mescolarlo con la nuova Theming API di AG Grid.
|
||||
|
||||
## Verifica prima del deploy server
|
||||
|
||||
Provare l'apertura dal menu Omics con un utente autorizzato e uno senza accesso;
|
||||
verificare assenza di un secondo login e di header ThothII, italiano/inglese già
|
||||
selezionati prima dell'apertura, tema, fullscreen e uscita con Esc. Ripetere con
|
||||
un menu o un form aperto, una bozza non inviata e una sessione esistente.
|
||||
|
||||
Verificare perdita dell'accesso, ritorno alla scheda e riconnessione degli eventi;
|
||||
distinguere questi casi dal rifiuto di una sola operazione. Controllare che una
|
||||
ripresa conservi la lingua salvata e che il reload non avvii una nuova generazione.
|
||||
Eseguire i test Omics nel suo ambiente Docker e includere gli aggiornamenti
|
||||
dei template, degli asset e dei cataloghi Django nel suo normale rebuild.
|
||||
|
||||
La verifica del codice e i test locali non costituiscono un deploy sul server
|
||||
di produzione. Usare il normale processo di rilascio per applicare entrambe le
|
||||
revisioni e annotare immagini, descrittore e revisioni realmente installate.
|
||||
@@ -0,0 +1,91 @@
|
||||
# Piano — Full shell e integrazione con il portale
|
||||
|
||||
Stato: implementazione completata e installata sul Mac; deploy server non eseguito.
|
||||
|
||||
Esiti e limiti del collaudo: [rapporto di verifica](../reports/2026-09-13-full-shell-implementation.md).
|
||||
|
||||
Specifica consolidata: [Full shell, integrazione Omics e interfaccia bilingue](2026-09-13-full-shell-spec.md),
|
||||
pubblicata come [specifica su Gitea](https://git.tylconsulting.it/mptyl/ThothII/issues/32).
|
||||
Ticket approvati: [Full sul Mac](https://git.tylconsulting.it/mptyl/ThothII/issues/33),
|
||||
[Embedded Omics](https://git.tylconsulting.it/mptyl/ThothII/issues/34),
|
||||
[Sessioni bilingui](https://git.tylconsulting.it/mptyl/ThothII/issues/35),
|
||||
[Traduzione completa](https://git.tylconsulting.it/mptyl/ThothII/issues/36),
|
||||
[Consegna verificata](https://git.tylconsulting.it/mptyl/ThothII/issues/37).
|
||||
Le dipendenze sono registrate anche nativamente sul tracker.
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Aggiungere una shell autonoma `full` mantenendo compatibile l'integrazione corrente `embedded`
|
||||
con Omics Portal. La complessità del portale deve restare confinata a un `PortalAdapter`.
|
||||
|
||||
## Regole definitive
|
||||
|
||||
- `embedded` è il default e non renderizza alcun header ThothII.
|
||||
- La configurazione installata su questo Mac imposta `shell.mode: full` e
|
||||
`shell.defaultLocale: en`.
|
||||
- Il deploy server imposta `shell.mode: embedded` e `shell.adapter: omics-portal`.
|
||||
- `full` renderizza header, rail sinistro vuoto di almeno 20 px e logout locale.
|
||||
- Fullscreen è uno stato separato dalla shell: il pulsante entra/esce dalla Fullscreen API e
|
||||
l'icona riflette anche l'uscita con `Esc`.
|
||||
- Full include lingua, tema `light/dark`, fullscreen e nome utente; non include la rotellina
|
||||
amministrativa.
|
||||
- Embedded riceve dal portale solo `locale`, `theme` e `fullscreen`; il server verifica l'accesso.
|
||||
- Login e logout embedded restano responsabilità di Omics Portal.
|
||||
- La lingua UI è separata dalla lingua di interazione fissata nella sessione.
|
||||
|
||||
## Sequenza di implementazione
|
||||
|
||||
### 1. Configurazione e stato shell
|
||||
|
||||
- Aggiungere `shell.mode`, `shell.defaultLocale` e `shell.adapter` al descrittore di
|
||||
installazione, mantenendo `embedded` come default quando `shell` non è presente.
|
||||
- Proiettare nel runtime frontend solo configurazione non segreta.
|
||||
- Centralizzare lo stato shell in un controller; i componenti non devono leggere direttamente
|
||||
il portale.
|
||||
|
||||
### 2. Adapter e bridge Omics
|
||||
|
||||
- Implementare `PortalAdapter` con la sola API `subscribe`.
|
||||
- Implementare `OmicsPortalAdapter` osservando il documento condiviso, secondo il contratto rivisto.
|
||||
- Leggere il locale dal selettore renderizzato da Django, osservare il tema e ascoltare il fullscreen.
|
||||
- Conservare il cambio lingua tramite reload Omics e il percorso server di autenticazione esistente.
|
||||
- Validare snapshot e cleanup; in caso di errore mostrare un messaggio di integrazione in
|
||||
embedded, senza fallback a controlli locali.
|
||||
|
||||
### 3. i18n e lingua del modello
|
||||
|
||||
- Introdurre cataloghi UI estendibili, inizialmente `it` e `en`, con fallback inglese.
|
||||
- Usare il locale corrente per le nuove sessioni.
|
||||
- Persistire nel manifest la lingua di interazione e usarla per domande, spiegazioni e scelte
|
||||
del revisore; una ripresa conserva quella lingua.
|
||||
- Non tradurre SQL, identificatori o contenuti del workspace.
|
||||
|
||||
### 4. Shell full
|
||||
|
||||
- Renderizzare header solo in `full`.
|
||||
- Collegare selettore lingua, tema, fullscreen, nome utente e logout alle funzioni già esistenti
|
||||
o equivalenti del frontend/backend.
|
||||
- Implementare il cambio icona e la sincronizzazione con `fullscreenchange`.
|
||||
- Applicare il rail sinistro vuoto con larghezza base semplice e non inferiore a 20 px.
|
||||
|
||||
### 5. Verifica
|
||||
|
||||
- Unit test per validazione adapter, cambio stato, fallback locale e regole di sessione.
|
||||
- Test frontend per entrambe le shell, logout full e fullscreen con `Esc`.
|
||||
- Test backend per il passaggio della lingua nelle nuove sessioni e la conservazione in resume.
|
||||
- Test di integrazione Omics per preferenze iniziali, tema, fullscreen, locale dopo reload e accesso.
|
||||
- Build frontend/backend, suite harness e build documentale.
|
||||
|
||||
## Fuori ambito
|
||||
|
||||
- Cambiare il proxy/authentication chain già operativo.
|
||||
- Passare a iframe o introdurre `postMessage`.
|
||||
- Trasferire token o oggetti utente nel browser bridge.
|
||||
- Aggiungere una shell `system` per il tema o un terzo tema.
|
||||
- Implementare un adapter per un secondo portale: deve solo essere possibile sostituire quello
|
||||
Omics tramite la stessa interfaccia.
|
||||
|
||||
## Gate di approvazione
|
||||
|
||||
L'implementazione è approvabile quando il codice rispetta il [contratto v1](../contracts/portal-shell-adapter-v1.md),
|
||||
la modalità embedded non mostra header proprio e la modalità full non dipende da Omics Portal.
|
||||
@@ -0,0 +1,99 @@
|
||||
# Full shell, integrazione Omics e interfaccia bilingue
|
||||
|
||||
## Problem Statement
|
||||
|
||||
ThothII è utilizzabile nel contenitore di Omics Portal, ma quando viene avviato
|
||||
autonomamente deve offrire i comandi generali che oggi appartengono al portale.
|
||||
Gli utenti devono poter scegliere italiano o inglese per l'interfaccia e per le
|
||||
nuove conversazioni con il modello, senza modificare la lingua dei contenuti del
|
||||
workspace. L'integrazione server deve conservare l'accesso già effettuato in Omics.
|
||||
|
||||
## Solution
|
||||
|
||||
Due modalità di installazione: Full Thoth Shell con header autonomo e Embedded
|
||||
Thoth Shell pilotata dall'header del portale. Sul Mac si installa full con inglese
|
||||
predefinito. Un Portal Shell Adapter sostituibile concentra le conoscenze Omics;
|
||||
l'autenticazione utilizza i percorsi già esistenti. La lingua di interazione
|
||||
rimane fissata per tutta la durata di una sessione, comprese le riprese.
|
||||
|
||||
## User Stories
|
||||
|
||||
1. As an operatore, I want scegliere full o embedded durante l'installazione, so that il contenitore corrisponda al luogo di utilizzo.
|
||||
2. As an operatore Mac, I want full con inglese predefinito, so that l'applicazione sia autonoma appena aperta.
|
||||
3. As an operatore di un'installazione precedente, I want mantenere embedded senza aggiungere configurazioni obbligatorie, so that un aggiornamento non interrompa l'integrazione Omics.
|
||||
4. As an utente full, I want un header con lingua, tema, fullscreen e nome utente, so that i comandi generali siano sempre raggiungibili.
|
||||
5. As an utente full, I want una fascia sinistra vuota di almeno 20 px bilanciata con lo spazio destro, so that il contenuto abbia margini coerenti.
|
||||
6. As an utente full, I want nessuna rotellina amministrativa del portale, so that il contenitore mostri solo i comandi richiesti.
|
||||
7. As an utente full, I want aprire il logout dal nome utente, so that possa terminare il mio accesso.
|
||||
8. As an utente locale, I want usare le credenziali ThothII esistenti, so that non debba configurare Omics.
|
||||
9. As an utente full con OIDC, I want terminare la sessione ThothII, so that il logout non sia limitato al login locale.
|
||||
10. As an utente Omics, I want aprire Datamart Builder già autenticato, so that non debba effettuare un secondo accesso.
|
||||
11. As an utente embedded, I want un solo header fornito da Omics, so that non compaiano comandi duplicati.
|
||||
12. As an utente embedded, I want che login e logout siano gestiti dal portale, so that l'accesso sia coerente con le altre pagine.
|
||||
13. As an utente embedded, I want che ThothII recepisca le preferenze già impostate prima dell'apertura, so that lingua e tema siano subito corretti.
|
||||
14. As an utente, I want scegliere light o dark, so that la leggibilità corrisponda alle condizioni ambientali.
|
||||
15. As an utente, I want leggere form, menu, errori e finestre anche in dark, so that il tema sia completo.
|
||||
16. As an utente full, I want entrare in fullscreen del browser, so that il browser lasci spazio all'applicazione.
|
||||
17. As an utente, I want vedere l'icona di uscita quando il fullscreen è attivo e l'icona iniziale dopo Esc, so that il comando rappresenti lo stato effettivo.
|
||||
18. As an utente, I want un messaggio comprensibile se il browser rifiuta il fullscreen, so that il controllo non mostri uno stato inesistente.
|
||||
19. As an utente, I want tutte le label e i testi non generati dal modello in italiano o inglese, so that possa usare l'applicazione nella lingua scelta.
|
||||
20. As an utente assistito da lettore di schermo, I want nomi accessibili e messaggi tradotti, so that i controlli siano utilizzabili quanto quelli visivi.
|
||||
21. As an utente embedded, I want il cambio lingua segua il normale ricaricamento Omics, so that tutta la pagina condivida la lingua.
|
||||
22. As an revisore, I want ritrovare la sessione dopo quel ricaricamento e proteggere le modifiche non salvate, so that non perda il lavoro.
|
||||
23. As an revisore, I want le nuove domande e scelte del modello nella lingua UI selezionata, so that l'interazione sia comprensibile.
|
||||
24. As an revisore, I want riprendere una sessione nella sua lingua originale, so that le preferenze del nuovo browser non cambino il workflow.
|
||||
25. As an revisore di sessioni precedenti, I want una regola stabile per i manifest privi della lingua di interazione, so that le riprese restino prevedibili.
|
||||
26. As an responsabile dei dati, I want conservare lingua e contenuto di workspace, SQL, identificatori e valori, so that una preferenza UI non alteri i dati.
|
||||
27. As an manutentore, I want aggiungere cataloghi per altre lingue con fallback inglese, so that l'i18n sia estendibile.
|
||||
28. As an integratore, I want sostituire OmicsPortalAdapter con un altro adapter della stessa interfaccia, so that un nuovo portale non richieda modifiche alle pagine o al workflow.
|
||||
29. As an utente il cui accesso scade, I want che lo stato protetto venga chiuso e il rientro segua il contenitore, so that non compaia un login ThothII in embedded.
|
||||
30. As an operatore, I want documentazione accurata di configurazione, autenticazione, adapter, migrazione e verifiche, so that il deploy server sia ripetibile.
|
||||
|
||||
## Implementation Decisions
|
||||
|
||||
- La configurazione installata distingue topologia, autenticazione e shell. Shell omessa significa embedded con adapter Omics predefinito; adapter sconosciuti sono errori espliciti. Full non istanzia adapter.
|
||||
- La configurazione frontend pubblica contiene soltanto dati non segreti e usa il meccanismo runtime esistente, compreso il prefisso API necessario al montaggio Omics.
|
||||
- Un controller di shell espone preferenze e stato; i componenti non accedono direttamente al portale.
|
||||
- L'interfaccia PortalAdapter offre una sottoscrizione con snapshot iniziale, aggiornamenti, errori e disiscrizione. Lo snapshot contiene locale, tema light/dark e fullscreen.
|
||||
- L'implementazione Omics legge la lingua effettivamente renderizzata dal selettore, osserva il tema sul documento e ascolta il fullscreen del browser. Non introduce handshake, eventi personalizzati o polling per le preferenze. Il contratto DOM è privato dell'adapter.
|
||||
- Il montaggio resta nello stesso documento. Nessun header o comando locale di autenticazione/presentazione viene introdotto in embedded.
|
||||
- Il server resta autorevole per identità e autorizzazioni. Il bridge UI non trasmette token, utente o flag authenticated. La catena di identità fidata esistente viene conservata.
|
||||
- I rifiuti di accesso all'applicazione devono essere distinti dai 403 relativi a una singola operazione. Ricontrollare l'accesso alla riconnessione e al ritorno alla pagina; non promettere revoca istantanea di altre schede tramite il solo proxy.
|
||||
- Full riutilizza login e logout esistenti, preserva le protezioni dalle modifiche non salvate e abilita il logout anche per sessioni ThothII OIDC. Il logout globale dall'identity provider non è implicito.
|
||||
- Fullscreen è indipendente dalla modalità full. L'icona segue lo stato effettivo e le richieste rifiutate sono gestite. I token dark esistenti vengono completati, con verifica dei contenuti sovrapposti e dell'isolamento degli stili embedded.
|
||||
- L'i18n utilizza cataloghi estendibili EN/IT con fallback inglese, comprese label, aiuti, placeholder, accessibilità, errori e widget deterministici. I payload tecnici restano stabili.
|
||||
- La lingua di interazione viene scelta dal locale UI risolto, salvata nel manifest e propagata al contesto del modello. Resume non accetta override dal browser.
|
||||
- Le sessioni precedenti prive del campo usano la lingua del workspace come compatibilità; il valore viene fissato alla prima ripresa mediante aggiornamento idempotente. Non si pretende di ricostruire una lingua storica non registrata.
|
||||
- Il cambio lingua Omics mantiene la navigazione Django. La selezione della sessione deve sopravvivere alla navigazione; le modifiche non salvate devono essere protette, senza avviare una nuova generazione implicitamente.
|
||||
|
||||
## Testing Decisions
|
||||
|
||||
I punti di verifica erano già approvati nel piano: comportamento della shell e
|
||||
dell'accesso dall'interfaccia, contratto pubblico dell'adapter, creazione/ripresa
|
||||
tramite API e CLI del workflow, configurazione d'installazione e integrazione
|
||||
Omics. Non si richiede una nuova approvazione degli stessi punti.
|
||||
|
||||
- Test comportamentali: stato osservabile, testo e controlli accessibili, permessi e lingua persistita; evitare metodi privati o asserzioni sull'organizzazione interna.
|
||||
- Riutilizzare i test AuthGate/AppShell con API simulate al confine HTTP, quelli delle route sessioni e quelli pubblici del repository/CLI del workflow.
|
||||
- Verificare adapter con un documento equivalente al template reale, preferenze iniziali, aggiornamenti e cleanup; includere montaggio ripetuto.
|
||||
- Verificare nuova sessione, resume con lingua UI diversa, manifest precedente e input locale invalido; il contesto fornito al modello deve contenere la lingua persistita.
|
||||
- Verificare fullscreen con ingresso, uscita, Esc e rifiuto; entrambe le modalità con dark, form e menu aperti.
|
||||
- Verificare accesso embedded senza secondo login, scadenza/403, riconnessione degli eventi e ritorno a una scheda; verificare logout full e protezione dei dati di un utente precedente.
|
||||
- Typecheck e test mirati durante lo sviluppo; suite complete alla fine, build documentale e prova browser proporzionata. Non usare chiamate reali al modello per i test deterministici.
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- Deploy sul server di produzione o modifica delle credenziali.
|
||||
- Seconda implementazione per un portale futuro, iframe e protocollo postMessage.
|
||||
- Nuovo sistema di autenticazione, propagazione di token nel browser o logout globale OIDC.
|
||||
- Tema system, ingresso automatico in fullscreen, rotellina amministrativa nell'header full.
|
||||
- Traduzione di SQL, dati, identificatori o contenuti del workspace; traduzione a posteriori delle decisioni generate dal modello.
|
||||
- Persistenza di una trascrizione integrale delle conversazioni.
|
||||
|
||||
## Further Notes
|
||||
|
||||
La revisione della semplificazione del 2026-09-13 è stata approvata dall'utente e
|
||||
prevale sui dettagli superati del primo contratto a eventi. La specifica consolida
|
||||
le decisioni senza riaprire l'intervista. Le modifiche vengono revisionate sui due
|
||||
assi Standards/Spec e committate sul branch corrente, preservando i cambiamenti
|
||||
preesistenti estranei a questa funzionalità.
|
||||
@@ -0,0 +1,129 @@
|
||||
# Full shell, Omics e interfaccia bilingue — verifica
|
||||
|
||||
Data: 2026-09-13. Specifica: [Full shell, integrazione Omics e interfaccia bilingue](../plans/2026-09-13-full-shell-spec.md).
|
||||
I cinque ticket e le loro dipendenze sono elencati nel [piano](../plans/2026-09-13-full-shell-and-portal-integration.md).
|
||||
|
||||
## Risultato
|
||||
|
||||
- Configurazione pubblica generata dal descrittore installato; full ed embedded
|
||||
usano la stessa immagine frontend. Sul Mac: `full`, locale iniziale `en`.
|
||||
- Header full con lingua, tema, fullscreen reale e menu utente/logout; rail sinistro
|
||||
vuoto di almeno 20 px. Nessuna rotellina amministrativa.
|
||||
- Embedded senza header locale; `OmicsPortalAdapter` incapsula l'osservazione del
|
||||
portale. Identità e autorizzazioni rimangono verificate dal server.
|
||||
- Cataloghi EN/IT, traduzioni dei controlli delle griglie, grafici e SQL adattati
|
||||
al tema. I contenuti di dominio rimangono invariati.
|
||||
- `interaction_language` fissata nel manifest: cattura alla creazione, mantenimento
|
||||
alla ripresa e assegnazione atomica del valore workspace per sessioni precedenti.
|
||||
- Continuità della selezione al reload, nessuna ripresa automatica del modello e
|
||||
protezione delle bozze non inviate.
|
||||
|
||||
La [guida operativa](../operations/shell-and-localization.md) descrive configurazione,
|
||||
accesso, estensione ad altri portali/lingue e checklist di deploy.
|
||||
|
||||
## Verifiche automatiche
|
||||
|
||||
| Livello | Esito |
|
||||
| --- | --- |
|
||||
| CLI nativa Go | `go test ./...`: 21 package verificati |
|
||||
| Harness Python | 1290 passati, 1 saltato, 6 L2 esclusi |
|
||||
| Gate Pi JavaScript | 205 passati |
|
||||
| Frontend | suite completa: 755 passati in 90 file; regressione CSS prebuild superata |
|
||||
| Backend | suite completa Node 24: 1397 passati, 40 saltati |
|
||||
| Omics Docker isolato | 15 test Django/integrazione passati; controlli JavaScript del browser inclusi |
|
||||
| Cataloghi | 1666 messaggi italiani, 1701 riferimenti statici; conflitti e interpolazioni verificati |
|
||||
| Build | frontend, backend/typecheck e documentazione MkDocs strict verificati; regressione CSS eseguita automaticamente prima della build frontend |
|
||||
|
||||
La suite backend richiede Node 24. Sul Mac il percorso Homebrew `node@24`
|
||||
risolveva a Node 25; è stato usato esplicitamente Node 24.16.0 già presente in NVM,
|
||||
senza modificare il runtime globale. Un test preesistente sul timeout di arresto
|
||||
di un processo è fallito sotto carico parallelo ed è passato isolatamente;
|
||||
la verifica finale usa un solo worker.
|
||||
|
||||
I test coprono comportamenti pubblici e confini approvati: manifest filesystem e
|
||||
PostgreSQL, CLI, Fastify, processo Pi simulato, stream SSE, shell e widget React,
|
||||
template/autorizzazione Omics. Non è stata avviata una nuova generazione L2 contro
|
||||
il modello remoto o il DWH operativo. Il controllo statico dei cataloghi non è
|
||||
una prova di traduzione di ogni possibile messaggio diagnostico esterno.
|
||||
|
||||
## Standards
|
||||
|
||||
Revisione indipendente rispetto al punto iniziale ThothII
|
||||
`2d1b714ebe31419d712e9c3324a5e171d5f0317d` e Omics `aff7581`.
|
||||
Due violazioni concrete del contratto: bozze dei gate non protette dal reload e
|
||||
selezione di sessioni altrui persa per gli amministratori. Entrambe corrette e
|
||||
riesaminate dal revisore indipendente. La protezione resta attiva anche durante
|
||||
un invio e dopo un errore HTTP, fino all'accettazione e allo smontaggio del widget.
|
||||
Nessun ulteriore rilievo concreto sul codice Omics o sulle euristiche di manutenibilità.
|
||||
Esito finale del revisore: approvato, zero rilievi aperti.
|
||||
|
||||
## Spec
|
||||
|
||||
Quattro rilievi: i due precedenti, più verifica dell'identità mancante dopo una
|
||||
riconnessione SSE riuscita ed errori deterministici dello stream non tradotti.
|
||||
Le correzioni includono test di regressione e sono state riesaminate dal revisore
|
||||
indipendente. Sono tradotti anche gli errori sanitizzati di avvio e le notifiche
|
||||
deterministiche dei gate già localizzate nella lingua fissata della sessione.
|
||||
Esito finale del revisore: tutti e quattro i rilievi chiusi, nessun nuovo rilievo
|
||||
o ampliamento ingiustificato dell'ambito.
|
||||
|
||||
Riepilogo iniziale: Standards 2 rilievi P2; Spec 4 rilievi P2. Gli assi restano
|
||||
separati; i rilievi comuni non rappresentano ulteriori difetti distinti.
|
||||
Riepilogo finale: Standards 0 aperti; Spec 0 aperti.
|
||||
|
||||
## Collaudo visivo
|
||||
|
||||
Il collaudo con l'account locale autenticato ha trovato tre difetti non visibili
|
||||
nei test DOM dei componenti:
|
||||
|
||||
1. Il contenitore CSS `@scope` includeva l'intero livello base Tailwind e nel browser
|
||||
integrato non applicava i token. Il CSS era servito con HTTP 200, ma il font
|
||||
effettivo era Times e `--background` risultava vuoto. L'isolamento del reset
|
||||
è ora compilato in selettori ordinari, senza modificare gli stili del portale.
|
||||
Il browser applica Manrope e i token light/dark corretti. Revisione indipendente
|
||||
del CSS compilato: nessuna perdita di isolamento individuata.
|
||||
2. La classe full costruita per interpolazione faceva eliminare il token del
|
||||
margine dalla build Tailwind. Nomi di classe letterali e una regressione sulla
|
||||
presenza di `--thot-shell-gutter` rendono il requisito verificabile nella build.
|
||||
3. Le griglie amministrative caricavano il tema CSS preesistente insieme al nuovo
|
||||
tema automatico della libreria. Griglie amministrative e anteprime ora usano
|
||||
un solo sistema CSS con i token della shell, eliminando il conflitto. I token
|
||||
vengono applicati anche ai contenitori di tema interni creati da AG Grid,
|
||||
che altrimenti sovrascriverebbero i colori ereditati.
|
||||
|
||||
Questi controlli sono stati eseguiti prima del commit di consegna. Il nuovo test
|
||||
`scripts/scoped-base.test.mjs` viene eseguito dal comando `prebuild` anche in Docker.
|
||||
Le prove di lingua/tema non hanno modificato dati del catalogo o avviato sessioni.
|
||||
|
||||
## Installazione locale e recupero
|
||||
|
||||
Il binario nativo aggiornato è installato in `/usr/local/bin/tht`.
|
||||
Il descrittore locale, non versionato, è
|
||||
`deploy/psd/thothii-installation.yaml`; `installation generate` ha prodotto:
|
||||
|
||||
```javascript
|
||||
window.__THOTHII_CONFIG__ = {"backendBaseUrl":"/api","shell":{"mode":"full","defaultLocale":"en"}};
|
||||
```
|
||||
|
||||
Il progetto Docker locale è `thothii-18998cca7b0a`; l'aggiornamento riguarda soltanto
|
||||
core/frontend. Database, Qdrant, embedding e volumi persistenti restano invariati.
|
||||
Le immagini precedenti sono conservate come
|
||||
`thothii-core:before-full-shell-20260913` e
|
||||
`thothii-frontend:before-full-shell-20260913`.
|
||||
Binario e descrittore precedenti sono in `/private/tmp/thothii-shell-install.8idNoC`
|
||||
(copia temporanea locale, non backup permanente).
|
||||
|
||||
Il sorgente Omics aggiornato è registrato nel commit locale `95154e1`.
|
||||
Nessun push o deploy sul server di produzione è stato eseguito. Il collaudo
|
||||
operativo sul server resta una fase del normale rilascio, seguendo la guida.
|
||||
|
||||
Core/frontend locali aggiornati e healthy; `/api/health` restituisce 200,
|
||||
`/config.js` espone full/en e `/api/auth/config` conferma l'accesso locale.
|
||||
Con l'account locale autenticato sono stati controllati header, cambio EN/IT,
|
||||
light/dark, menu utente/logout, ingresso/uscita fullscreen tramite pulsante e
|
||||
margini effettivi di 24 px. I test automatici coprono logout e sincronizzazione
|
||||
con `fullscreenchange`, compreso il ritorno allo stato normale. L'uscita tramite
|
||||
tasto Esc nativo resta da provare in un browser desktop ordinario: il comando
|
||||
di tastiera automatizzato del browser integrato non l'ha riprodotta. Nessuna
|
||||
promessa di collaudo completo del browser del server è implicita in queste prove.
|
||||
Le preferenze locali sono state riportate a inglese e tema chiaro.
|
||||
@@ -0,0 +1,195 @@
|
||||
# Revisione della semplificazione della shell
|
||||
|
||||
Data: 2026-09-13. Oggetto: piano full/embedded, ADR 0021–0022 e contratto
|
||||
Portal Shell Adapter v1. Questa è una revisione con raccomandazioni: non modifica il
|
||||
codice applicativo né sostituisce automaticamente i contratti accettati.
|
||||
|
||||
## Valutazione
|
||||
|
||||
La separazione tra shell, autenticazione e lingua delle sessioni è corretta. La
|
||||
semplificazione precedente ha però mantenuto un protocollo di comunicazione non
|
||||
necessario per il montaggio corrente e ha lasciato ambigue alcune condizioni di
|
||||
compatibilità. Raccomando un adapter che osservi il documento già condiviso con
|
||||
Omics, riutilizzi l'autenticazione esistente e non imponga un nuovo bridge al portale.
|
||||
|
||||
La revisione considera il sorgente locale di ThothII e Omics Portal al commit
|
||||
`aff7581`, già ottenuto con il pull richiesto. Non certifica quali immagini,
|
||||
configurazioni o modifiche siano attualmente attive sul server.
|
||||
|
||||
## Problemi individuati e correzioni raccomandate
|
||||
|
||||
### 1. Il cambio lingua senza ricaricamento non corrisponde a Omics
|
||||
|
||||
In `templates/partials/topbar.html:74–87`, Omics usa il form Django `set_language`
|
||||
con `onchange="this.form.submit()"`. La lingua cambia attraverso una nuova pagina
|
||||
renderizzata dal server. Il criterio 2 del contratto v1 promette invece aggiornamenti
|
||||
senza ricaricamento per tutte le preferenze.
|
||||
|
||||
Raccomandazione: rispettare il comportamento del portale. In full, lingua e tema
|
||||
cambiano immediatamente. In embedded, il tema cambia immediatamente e la lingua
|
||||
segue il normale ricaricamento Omics. Evitare di intercettare il form per cambiare
|
||||
solo ThothII: lascerebbe header, sidebar e testi Django nella lingua precedente.
|
||||
|
||||
Il ricaricamento va verificato durante una sessione attiva e con modifiche non
|
||||
salvate: deve essere possibile ritrovare la sessione senza avviare una nuova
|
||||
generazione; eventuali bozze richiedono una protezione dalla navigazione. Lo stato
|
||||
persistito del workflow non equivale alla conservazione automatica della bozza UI
|
||||
o del flusso di messaggi in memoria. Questa verifica è necessaria anche mantenendo
|
||||
il protocollo a eventi del piano precedente.
|
||||
|
||||
### 2. Un protocollo ready/state non è necessario nello stesso documento
|
||||
|
||||
`templates/kokoro/datamart_builder.html` monta React in `#root`, nello stesso
|
||||
documento dell'header. L'adapter può ottenere direttamente:
|
||||
|
||||
- lingua effettivamente renderizzata: `data-lang` del selettore
|
||||
`.omics-language-select`;
|
||||
- tema: attributo `data-bs-theme` sull'elemento `html`;
|
||||
- fullscreen: stato del documento e relativo evento del browser.
|
||||
|
||||
Un'osservazione limitata all'attributo del tema e un listener del fullscreen
|
||||
coprono gli aggiornamenti attuali. La lingua viene riletta quando Django restituisce
|
||||
la pagina. Questi selettori e dettagli devono comparire soltanto dentro
|
||||
`OmicsPortalAdapter`, con test basati sul template reale.
|
||||
|
||||
Attenzione: `templates/base.html:3` contiene oggi `lang="en"` fisso; quell'attributo
|
||||
non è una fonte attendibile per la lingua Omics. Se in futuro il portale espone la
|
||||
lingua su un attributo dedicato del punto di montaggio, si modifica soltanto l'adapter.
|
||||
|
||||
La proposta elimina due eventi personalizzati, la versione del protocollo, il
|
||||
timeout di avvio e il rischio che il messaggio iniziale parta prima del listener.
|
||||
L'osservazione va installata prima di consegnare lo snapshot iniziale; la funzione
|
||||
di disiscrizione rimuove tutte le risorse. L'assenza dei dati Omics attesi produce
|
||||
un errore di integrazione comprensibile, senza attivare la shell full.
|
||||
|
||||
Il costo accettato è una dipendenza esplicita dal piccolo contratto DOM Omics,
|
||||
confinata nell'adapter. Un secondo portale potrà fornire gli stessi dati usando
|
||||
un'altra implementazione, anche con un diverso trasporto. Non occorre costruirla ora.
|
||||
|
||||
### 3. `authenticated` duplica uno stato che il server già verifica
|
||||
|
||||
`kokoro/datamart_catalog_views.py:49` e `nginx/nginx.conf:69` verificano l'accesso
|
||||
Omics e trasmettono al backend identità e autorizzazioni normalizzate. ThothII
|
||||
ottiene già l'utente tramite `/me`. Non serve un ulteriore login né un flag nel
|
||||
documento che dichiari l'utente autenticato.
|
||||
|
||||
Il logout Omics attuale è una navigazione (`topbar.html:118`), non un evento di
|
||||
revoca. Un click sul link non prova che il logout sia stato completato; inoltre,
|
||||
un flag inviato una volta non rileva la scadenza della sessione o un logout in
|
||||
un'altra scheda.
|
||||
|
||||
Raccomandazione: togliere `authenticated` dallo snapshot visivo. La verifica
|
||||
dell'accesso rimane nel percorso di autenticazione esistente. In embedded,
|
||||
perdita dell'accesso significa chiudere i dati protetti e demandare il rientro
|
||||
al portale, senza mostrare il form di login ThothII.
|
||||
|
||||
Serve verificare la gestione dei rifiuti Omics: l'endpoint di autorizzazione
|
||||
restituisce attualmente 403 anche quando l'accesso non è disponibile, mentre
|
||||
`frontend/src/api/client.ts` pulisce automaticamente lo stato su 401. Un 403
|
||||
ordinario può anche significare che manca il permesso per una sola operazione;
|
||||
non va trasformato indiscriminatamente in logout. La verifica `/me` deve
|
||||
distinguere la perdita di accesso all'applicazione dal rifiuto di una sua funzione.
|
||||
|
||||
`frontend/src/stream/useSessionStream.ts` esegue già un controllo di autenticazione
|
||||
quando il collegamento eventi fallisce: riutilizzare quel percorso. Non promettere
|
||||
revoca istantanea di una connessione già aperta in un'altra scheda sulla sola base
|
||||
di `auth_request` o di un evento nella pagina corrente. Il contratto deve dichiarare
|
||||
quando l'accesso viene ricontrollato e verificare anche il ritorno a una scheda
|
||||
rimasta aperta.
|
||||
|
||||
In full sul Mac resta il login locale esistente. Il logout backend esiste già
|
||||
(`backend/src/auth/routes.ts:355`): il lavoro riguarda il collegamento all'header
|
||||
e la pulizia della UI. Per installazioni full con OIDC va consentito anche quel
|
||||
logout; oggi `AuthGate` lo espone soltanto per `mode === "local"`. La revoca della
|
||||
sessione ThothII non va descritta come logout globale dal fornitore d'identità.
|
||||
|
||||
### 4. Il default embedded contraddice l'adapter obbligatorio
|
||||
|
||||
Il piano dichiara compatibilità con descrittori senza `shell`, ma il contratto
|
||||
richiede `adapter` in embedded. Inoltre, pretendere un nuovo bridge renderebbe
|
||||
inutilizzabile la vecchia pagina Omics finché non fosse aggiornata.
|
||||
|
||||
Raccomandazione: risolvere i valori in un unico punto di configurazione:
|
||||
|
||||
- assenza di `shell`: embedded con adapter Omics predefinito;
|
||||
- embedded senza `adapter`: `omics-portal`;
|
||||
- full: nessun adapter istanziato;
|
||||
- nome adapter sconosciuto: errore esplicito di configurazione.
|
||||
|
||||
L'adapter che legge lo stato già esistente rende questa compatibilità concreta.
|
||||
Sul Mac rimangono espliciti `mode: full` e `defaultLocale: en`. La proiezione
|
||||
pubblica può usare il `config.js` già presente; non serve un nuovo servizio di
|
||||
configurazione. Va verificato anche il prefisso API `/datamart-builder/api` nel
|
||||
montaggio Omics: il default frontend `/api` non basta a dimostrare che il deploy
|
||||
funzioni. Prima si aggiorna il lettore del descrittore, poi il file installato,
|
||||
poiché il lettore corrente rifiuta chiavi sconosciute.
|
||||
|
||||
### 5. Fullscreen e dark mode hanno già elementi riutilizzabili
|
||||
|
||||
ThothII possiede già token scuri in `frontend/src/index.css:67`, attivati anche da
|
||||
`data-bs-theme="dark"`. Il lavoro è completarne la copertura e verificare contrasto,
|
||||
form, menu e finestre, riutilizzando questi token.
|
||||
|
||||
Omics cambia la classe `fullscreen-enable` al click (`static/js/app.js:702`)
|
||||
prima di conoscere il risultato. Il ramo di uscita usa metodi storici e non
|
||||
contiene `document.exitFullscreen()`. Non va copiato nella shell full: l'icona
|
||||
deve seguire lo stato effettivo, compresi Esc e richieste rifiutate. La correzione
|
||||
equivalente dell'header Omics appartiene al suo modulo UI, non a un secondo
|
||||
controllo fullscreen dentro ThothII embedded.
|
||||
|
||||
La fascia vuota sinistra si realizza con una misura CSS condivisa, almeno 20 px,
|
||||
bilanciata con lo spazio destro. Non richiede un modulo di navigazione vuoto.
|
||||
Poiché il documento è condiviso, verificare anche che stili globali ThothII e
|
||||
contenuti sovrapposti non alterino header e sidebar del portale: il template Omics
|
||||
contiene già correzioni per reset CSS e altezza `100vh`.
|
||||
|
||||
## Elementi da conservare
|
||||
|
||||
La lingua dell'interfaccia, quella delle domande al revisore e quella dei contenuti
|
||||
del workspace hanno proprietari e durate diverse. Conservare la separazione di
|
||||
ADR 0022: semplificarla in un'unica preferenza globale introdurrebbe errori in
|
||||
ripresa e nei workspace italiani.
|
||||
|
||||
Precisare tre regole d'implementazione:
|
||||
|
||||
- una nuova sessione salva il locale UI effettivamente risolto, dopo il fallback
|
||||
delle traduzioni;
|
||||
- una sessione esistente conserva la propria lingua anche se un altro revisore
|
||||
usa un'interfaccia diversa;
|
||||
- per manifest precedenti senza campo lingua, usare la lingua del workspace come
|
||||
criterio di compatibilità e fissarla alla prima ripresa con un aggiornamento
|
||||
idempotente. Non dedurla dalla lingua del browser del nuovo revisore. La lingua
|
||||
storica esatta non è ricostruibile se il workspace è stato cambiato nel frattempo.
|
||||
|
||||
L'i18n resta il lavoro trasversale principale: include pagine amministrative,
|
||||
errori, accessibilità e testi deterministici dei widget, anche quelli costruiti
|
||||
fuori da React. Aggiungere soltanto i cataloghi dell'header non soddisfa la richiesta.
|
||||
Il modello deve ricevere la lingua dal manifest autorevole, senza tradurre a
|
||||
posteriori payload delle decisioni, SQL o contenuti del workspace.
|
||||
|
||||
## Struttura raccomandata
|
||||
|
||||
Un solo controller di shell alimenta l'interfaccia. In full gestisce preferenze
|
||||
locali e header; in embedded riceve `{ locale, theme, fullscreen }` da un
|
||||
`PortalAdapter.subscribe(...)`. I componenti applicativi usano quello stato e
|
||||
non conoscono Omics. Nessun registro dinamico di plugin, protocollo di comandi o
|
||||
controller separato per ciascun pulsante.
|
||||
|
||||
L'autenticazione continua a usare il modulo esistente, con presentazione dell'accesso
|
||||
coerente con la shell. L'integrazione con un futuro portale richiede anche che il
|
||||
suo lato server soddisfi il contratto di identità verificata: sostituire una classe
|
||||
JavaScript non può da solo sostituire l'autenticazione server. Documentare insieme
|
||||
l'adapter UI e la configurazione server Omics, senza introdurre nuove dipendenze
|
||||
Omics nel workflow o nelle pagine ThothII.
|
||||
|
||||
## Verifiche necessarie prima della consegna
|
||||
|
||||
Verificare full sul Mac con default inglese, accesso/logout, tema e fullscreen;
|
||||
embedded sul template Omics, con preferenze già impostate prima del montaggio,
|
||||
cambio tema e lingua, Esc, assenza di header ThothII e descrittore precedente.
|
||||
Verificare nuova sessione, ripresa, manifest precedente, ricaricamento durante
|
||||
la revisione e perdita dell'accesso con collegamento eventi attivo.
|
||||
|
||||
Sono verifiche del comportamento, non motivi per costruire un'infrastruttura
|
||||
generica. Questa revisione si basa sull'ispezione del sorgente; non sono stati
|
||||
eseguiti test runtime né modificati i due applicativi.
|
||||
Reference in New Issue
Block a user