32 KiB
Upgrade del server alla configurazione ThothII v2
Questo runbook è il passaggio di consegne per il Codex che opererà sul server remoto. Porta una installazione precedente alla configurazione corrente di ThothII senza modificare Authentik o il DWH esterno e senza cancellare lo stack precedente durante il primo cutover.
Scelta preliminare: server autonomo oppure Omics
I passaggi di questo runbook che configurano OIDC diretto, gruppi e
authentication.runtimeProjection riguardano ThothII autonomo, da rendere
con shell.mode: full. Non applicarli all'integrazione Datamart Builder: Omics
usa embedded/upstream e mantiene il proprio accesso Authentik. Il core riceve
l'identità verificata dal proxy senza un secondo login né un secondo auth.yaml.
Prima dell'inventario identificare quale percorso è approvato. Per Omics seguire
autenticazione upstream e
rilascio coordinato dei due repository;
i gate di backup, isolamento, catalogo, storage e rollback di questo runbook
rimangono validi, ma non copiare i passi auth del percorso autonomo. Il passaggio
da issuer portal a un issuer OIDC differente non trasferisce automaticamente
la proprietà delle sessioni.
La procedura si applica a main quando contiene almeno il commit
eba6148511675fc6a187aabb69a975adc5e3c542. Deve essere presente anche questo file. Il commit
minimo è un controllo di sicurezza, non un invito a fermarsi a quella revisione: installare sempre
la origin/main approvata dall'operatore.
Regole non negoziabili
- Per le modifiche al portale Omics seguire prima la
consegna via GitHub e server verso Gitea PSD.
L'operatore lavora in
/home/chirone/omics_portal: fetch del branch dedicato da GitHub, verifica SHA, push esplicito a Gitea. Il trasferimento non modifica il checkout di produzione e non autorizza un deploy; non cercare credenziali Gitea PSD sul Mac per aggirare questa procedura concordata. - Eseguire prima l'intero inventario in sola lettura e consegnarlo all'operatore.
- Non stampare mai password, token, chiavi private, cookie, file
.envo contenuti dei Docker secret. Nei report sono ammessi solo percorsi, nomi delle variabili e valori non segreti. - Non usare
set -x, credenziali dentro URL Git,http.sslVerify=false,docker compose down -v,docker volume rm,git reset --hardo pulizie ricorsive. - Non inventare l'indirizzo IP di
git.tylconsulting.ite non aggiungerlo a/etc/hostssenza un valore e un fingerprint TLS forniti dall'amministratore. - Non sovrascrivere la vecchia configurazione. Creare una nuova installation ID e mantenere configurazione, immagini, container e volumi precedenti fino all'accettazione scritta.
- Fermarsi a ogni Gate operatore. Il Codex prepara evidenze e comandi esatti; l'operatore autorizza backup con segreti, fermo dello stack, cambio del reverse proxy e rimozioni.
- Il DWH resta read-only e diretto. Nessuna migrazione o DDL deve essere eseguita sul DWH.
Cosa contiene la nuova release
Il confine informale “da auth in poi” non coincide con un singolo commit Git. OIDC/Authentik e il
CLI host tht fanno parte del contratto che il nuovo server deve rispettare, ma la tranche promossa
da f5861526 a eba61485 riguarda soprattutto:
- Database Management e il catalogo metadati isolato nel PostgreSQL interno
catalog-db; - sincronizzazione di tabelle, colonne e relazioni, generazione descrizioni e flag di sensibilità;
- Installation Model Catalog schema v2 come unica sorgente authored per modelli e provider;
- workspace schema v4 e proiezioni runtime generate;
- Qdrant per gli indici del workspace e Ollama per il solo modello di embedding;
- analisi locale deterministica delle colonne sensibili, con NER CPU opzionale;
- hardening delle proiezioni e stabilizzazione dei gate di test pre-deploy.
La topologia base attesa è:
| Servizio | Funzione | Persistenza |
|---|---|---|
frontend |
UI React | nessuna persistenza propria |
core |
Fastify, Pi RPC e catalog API | volumi settings, Pi, registry, secrets e sessioni |
catalog-db |
PostgreSQL del catalogo metadati | volume catalog-data |
catalog-migrate |
migrazioni esplicite del catalogo | job one-shot, deve terminare con exit 0 |
qdrant |
indice vettoriale workspace | volume qdrant-data |
embedding |
Ollama interno per embedding | volume embedding-models |
embedding-model-init |
scarica/verifica il modello | job one-shot, deve terminare con exit 0 |
catalog-db non è il DWH. Non pubblica porte sull'host e usa credenziali runtime e migrator
separate. Ollama non controlla le password utente: nel percorso autonomo vale
OIDC tramite Authentik; nel percorso embedded Omics verifica l'accesso e il core
usa upstream.
Il PostgreSQL per le sessioni è un'altra funzione ancora. L'overlay
deploy/compose.session-server.yaml.example è esplicitamente opt-in: non abilitarlo durante questo
upgrade salvo decisione separata dell'operatore e presenza di un database sessioni già
provisionato. L'introduzione richiesta qui è soltanto catalog-db.
Stato finale desiderato
Sono due repository distinti e non devono essere confusi:
| Uso | Remote atteso | Branch | Trasporto |
|---|---|---|---|
codice applicativo ThothII, remote origin |
https://git.tylconsulting.it/mptyl/ThothII.git |
main |
HTTPS |
workspace PSD, workspaceRepository |
git@github.com:mptyl/tht-workspace-psd.git |
main |
SSH |
Il riferimento locale approvato usa il workspace precedente e questi default di modello:
- sessione:
zai/glm-5.3; - generazione metadati:
zai/glm-5.3; - embedding:
ollama/qwen3-embedding:0.6b, 1024 dimensioni.
Non copiare i file generati locali. La sorgente authored è il nuovo
thothii-installation.yaml; i file Pi, settings, catalogo runtime e Compose derivati vengono
rigenerati da tht.
0. Preparare le variabili di lavoro
Usare percorsi assoluti reali. I valori seguenti sono esempi e vanno sostituiti dopo l'inventario:
THTII_REPO=/absolute/path/to/ThothII
THTII_GITEA_URL=https://git.tylconsulting.it/mptyl/ThothII.git
THTII_MIN_COMMIT=eba6148511675fc6a187aabb69a975adc5e3c542
THTII_NEW_ID=psd-server-v2
THTII_WORKSPACE_REMOTE=git@github.com:mptyl/tht-workspace-psd.git
THTII_WORKSPACE_BRANCH=main
THTII_OLD_INSTALLATION=/absolute/path/to/legacy/thothii-installation.yaml
THTII_NEW_INSTALLATION=/absolute/path/to/ThothII/deploy/psd-server-v2/thothii-installation.yaml
THTII_NEW_ENV=/absolute/path/to/ThothII/deploy/psd-server-v2/operator.env
THTII_BACKUP_ARCHIVE=/protected/backups/thothii-pre-v2-YYYYMMDD.zip
THTII_SECRETS_FILE=/protected/thothii-v2/thothii.secrets
THTII_PI_AUTH_FILE=/protected/thothii-v2/pi-auth.json
THTII_CATALOG_RUNTIME_PASSWORD=/protected/thothii-v2/catalog-runtime-password
THTII_CATALOG_MIGRATOR_PASSWORD=/protected/thothii-v2/catalog-migrator-password
THTII_WORKSPACE_SSH_KEY=/protected/thothii-v2/workspace-deploy-key
THTII_WORKSPACE_KNOWN_HOSTS=/protected/thothii-v2/workspace-known-hosts
THTII_PUBLIC_URL=https://thothii.example.invalid
THTII_AUTH_ISSUER=https://authentik.example.invalid/application/o/thothii/
THTII_AUTH_CLIENT_ID=replace-with-approved-client-id
THTII_AUTHENTIK_URL=https://authentik.example.invalid
Definire inoltre, senza pubblicarne il contenuto:
- percorso del descriptor e comando di avvio della vecchia installazione;
- installation ID, Compose project, porte e reverse-proxy route correnti;
- percorsi protetti per secret bundle, Pi auth, chiave SSH GitHub e
known_hosts; - Public URL, issuer, client ID, URL Authentik e nomi dei gruppi;
- host, porta, database, utente e CA del binding diretto DWH;
- directory persistenti e directory backup della nuova installazione.
Esito richiesto: tutte le variabili indicano target esistenti o percorsi nuovi approvati; nessun valore segreto compare nel terminale condiviso.
1. Inventario in sola lettura del server
Non fare ancora fetch, checkout, stop o modifica di remote. Dal checkout esistente raccogliere:
cd "$THTII_REPO"
git status --short --branch
git branch --show-current
git rev-parse HEAD
git remote -v
git tag --points-at HEAD
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'
docker volume ls
df -h
tht version --json
Se tht non esiste ancora, registrarlo come assente senza installarlo in questo passo. Individuare
anche i container realmente appartenenti al vecchio stack, i loro image ID, i volumi montati e il
comando esatto che oggi li avvia. Non assumere nomi dai file della nuova release.
Raccogliere in forma redatta:
- configurazione Authentik attuale: Public URL, issuer, client ID, callback, claim gruppi e gruppi ruolo; non leggere in output client secret o API token;
- binding DWH diretto: tipo
postgres_direct, endpoint, database e utente; non stampare password; - remote, branch e revisione del vecchio workspace;
- stato delle sessioni e directory dati che devono essere conservate;
- spazio disponibile per immagini, volume Ollama, Qdrant, catalogo e backup.
Se il worktree è sporco o contiene configurazioni non committate, fermarsi: descrivere file e proprietario delle modifiche, senza fare stash, reset o checkout.
Esito richiesto: un report redatto identifica vecchio stack, dati, immagini, rete, Authentik, DWH e workspace; il worktree è pulito oppure l'operatore ha risolto esplicitamente le differenze.
2. Rendere Gitea raggiungibile e assegnarlo a origin
“Impostare Gitea come origin” e “risolvere il dominio Gitea” sono due operazioni diverse. Verificare prima DNS e TLS:
getent hosts git.tylconsulting.it
curl --fail --silent --show-error --head https://git.tylconsulting.it/
Se getent non è disponibile, usare il resolver diagnostico già installato, per esempio
dig +short git.tylconsulting.it. Se il nome non risolve, fermarsi e chiedere la correzione DNS o
la mappatura IP ufficiale. Se TLS fallisce per una CA interna, installare la CA fornita
dall'amministratore nel trust store; non disabilitare la verifica.
Quando rete e TLS sono validi, registrare l'URL corrente di origin nel report e configurare Gitea:
cd "$THTII_REPO"
git remote get-url origin
git remote set-url origin "$THTII_GITEA_URL"
git remote -v
git ls-remote --exit-code origin refs/heads/main
Se origin non esiste, usare git remote add origin "$THTII_GITEA_URL" al posto di
set-url. Se serve autenticazione HTTPS, configurare il credential helper o il token nel secret
store del server; non inserire il token nell'URL o nella shell history.
Esito richiesto: origin mostra l'URL Gitea esatto per fetch e push e ls-remote restituisce
refs/heads/main. Non eseguire push dal server.
3. Fare fetch e aggiornare main senza perdere il rollback
Con worktree pulito:
cd "$THTII_REPO"
git fetch --prune origin
git branch rollback/server-pre-v2-YYYYMMDD HEAD
git switch main
git merge --ff-only origin/main
git merge-base --is-ancestor "$THTII_MIN_COMMIT" HEAD
test -f docs/operations/server-upgrade-gitea-workspace-v2.md
git status --short --branch
git rev-parse HEAD
Sostituire YYYYMMDD con la data reale e registrare hash precedente, rollback branch e nuovo hash.
Un merge non fast-forward, un file mancante o il fallimento di merge-base sono condizioni di stop.
Non risolvere divergenze con reset o rebase sul server.
Esito richiesto: main coincide con la origin/main approvata, contiene il commit minimo e il
runbook, e il rollback branch punta ancora al vecchio HEAD.
4. Salvare vecchia installazione, dati e immagini
Gate operatore A — custodia del backup
Prima di leggere o archiviare secret, presentare l'elenco esatto dei file e volumi da salvare e ottenere l'autorizzazione. Il backup deve stare fuori dal repository, su storage protetto, con permessi restrittivi e checksum registrato separatamente.
Se il vecchio CLI espone backup e accetta il suo descriptor, usare il percorso esplicito:
umask 077
tht --installation "$THTII_OLD_INSTALLATION" backup \
--output "$THTII_BACKUP_ARCHIVE" --include-secrets --yes --drain
sha256sum "$THTII_BACKUP_ARCHIVE"
Se il vecchio formato non è accettato, usare la procedura di backup già approvata sul server. Non
improvvisare un archivio ricorsivo di /srv o della root. Il backup deve includere almeno:
- descriptor, env non segreto, configurazione auth canonica, secret bundle, Pi auth e certificati;
- repository/configurazione workspace precedente e sessioni persistite;
- inventario di container, reti, volumi, mount, image name e image ID;
- configurazione del reverse proxy necessaria a ripristinare il servizio.
Conservare anche le immagini effettivamente in uso: assegnare tag di rollback agli image ID espliciti identificati al passo 1 oppure salvarli in un archivio Docker protetto. Non selezionare immagini tramite glob. Il nuovo build può riutilizzare gli stessi tag mentre i container vecchi continuano a funzionare.
Il backup integrato va considerato sufficiente per un volume solo se il suo manifest lo elenca e la
procedura di restore è stata verificata. In questa migrazione il nuovo catalog-data nasce vuoto;
non esiste quindi un vecchio catalogo da importare. Per upgrade successivi, il catalogo PostgreSQL
dovrà avere un dump consistente esplicito se il backup corrente non lo comprende.
Esito richiesto: archivio, checksum, immagini di rollback e comando di ripristino sono verificati; nessun vecchio container o volume è stato eliminato.
5. Installare il CLI corrente e creare una installation v2 affiancata
Dal nuovo checkout:
cd "$THTII_REPO"
./scripts/install-tht.sh
tht version --json
Preparare fuori dal repository file protetti distinti per:
- secret bundle applicativo;
- Pi auth;
- password runtime e migrator di
catalog-db; - chiave privata e
known_hostsdel repository workspace GitHub.
Le due password del catalogo devono essere casuali, non vuote e diverse. I file devono essere
leggibili solo dall'operatore autorizzato. Nel secret bundle servono i riferimenti approvati per i
provider (ZAI_API_KEY e, se mantenuto, DEEPSEEK_API_KEY) e per Authentik
(THT_OIDC_CLIENT_SECRET, THT_AUTHENTIK_API_TOKEN), mai i valori nel descriptor YAML.
Verificare l'accesso SSH al workspace con la chiave e il file known_hosts approvati. Non costruire
known_hosts accettando alla cieca il primo fingerprint restituito dalla rete:
ssh-keygen -F github.com -f "$THTII_WORKSPACE_KNOWN_HOSTS"
GIT_SSH_COMMAND="ssh -i $THTII_WORKSPACE_SSH_KEY -o IdentitiesOnly=yes -o UserKnownHostsFile=$THTII_WORKSPACE_KNOWN_HOSTS" \
git ls-remote --exit-code "$THTII_WORKSPACE_REMOTE" refs/heads/main
Creare la configurazione server in modalità configure-only; il profilo server richiede root per
creare la proiezione auth con UID/GID del container. La versione corrente di setup non scrive
ancora i due path catalogo nell'env generato: passarli all'ambiente del comando per validare
Compose, quindi aggiungerli subito a operator.env nel passo successivo.
cd "$THTII_REPO"
sudo env \
THT_CATALOG_RUNTIME_PASSWORD_SOURCE="$THTII_CATALOG_RUNTIME_PASSWORD" \
THT_CATALOG_MIGRATOR_PASSWORD_SOURCE="$THTII_CATALOG_MIGRATOR_PASSWORD" \
tht setup --configure-only \
--installation-id "$THTII_NEW_ID" \
--profile server \
--workspace-remote "$THTII_WORKSPACE_REMOTE" \
--workspace-branch "$THTII_WORKSPACE_BRANCH" \
--workspace-access ssh \
--secrets-file "$THTII_SECRETS_FILE" \
--pi-auth-file "$THTII_PI_AUTH_FILE" \
--git-ssh-key-file "$THTII_WORKSPACE_SSH_KEY" \
--git-known-hosts-file "$THTII_WORKSPACE_KNOWN_HOSTS" \
--auth-mode oidc \
--auth-public-url "$THTII_PUBLIC_URL" \
--auth-issuer "$THTII_AUTH_ISSUER" \
--auth-client-id "$THTII_AUTH_CLIENT_ID" \
--auth-authentik-base-url "$THTII_AUTHENTIK_URL" \
--auth-user-group 'TOT Users' \
--auth-admin-group 'TOT Admin'
Se sul server i gruppi hanno nomi diversi, usare i nomi verificati al passo 1. Non indovinarli.
Registrare il descriptor prodotto, normalmente
deploy/<installation-id>/thothii-installation.yaml, e usarlo esplicitamente in ogni comando
successivo. Aggiungere all'operator.env generato, usando un editor che non stampi i valori:
THT_CATALOG_RUNTIME_PASSWORD_SOURCE=/protected/thothii-v2/catalog-runtime-password
THT_CATALOG_MIGRATOR_PASSWORD_SOURCE=/protected/thothii-v2/catalog-migrator-password
THT_CATALOG_SYNC_TIMEOUT_MS=600000
I valori a destra devono essere i percorsi assoluti reali preparati sopra. Verificare che
THTII_NEW_INSTALLATION e THTII_NEW_ENV corrispondano ai file appena creati.
Esito richiesto: esistono descriptor schema v2, env operatore e directory auth canonica/runtime della nuova installation; lo stack precedente è ancora in esecuzione.
6. Allineare il descriptor alla configurazione locale approvata
Il setup genera un catalogo modelli valido ma generico. Sostituire il suo blocco modelCatalog
con questo riferimento corrente, soltanto dopo aver verificato che il server raggiunga gli endpoint
necessari:
modelCatalog:
defaults:
session: zai/glm-5.3
metadataGeneration: zai/glm-5.3
embedding:
id: ollama/qwen3-embedding:0.6b
dimensions: 1024
providers:
deepseek:
authentication:
mode: pi_auth
session:
mode: pi_builtin
models:
deepseek-v4-pro:
session: {}
deepseek-v4-flash:
session: {}
deepseek-metadata:
authentication:
mode: secret_env
apiKeyEnv: DEEPSEEK_API_KEY
metadataGeneration:
litellmProvider: deepseek
models:
deepseek-v4-pro:
label: DeepSeek V4 Pro
metadataGeneration: {}
deepseek-v4-flash:
label: DeepSeek V4 Flash
metadataGeneration: {}
zai:
endpoint:
baseUrl: https://api.z.ai/api/coding/paas/v4
authentication:
mode: secret_env
apiKeyEnv: ZAI_API_KEY
session:
mode: openai_compatible
metadataGeneration:
litellmProvider: openai
models:
glm-5.3:
label: GLM 5.3
session:
reasoning: true
contextWindow: 200000
maxTokens: 131072
metadataGeneration: {}
local-qwen:
endpoint:
baseUrl: https://ml-aritmolab.policlinicosandonato.it/v1
authentication:
mode: none
session:
mode: openai_compatible
metadataGeneration:
litellmProvider: openai
models:
qwen3.6-35b-a3b:
label: AritmoLab Qwen 3.6 35B A3B
session:
reasoning: false
input: [text]
cost: {input: 0, output: 0, cacheRead: 0, cacheWrite: 0}
contextWindow: 131072
maxTokens: 16384
compatibility:
supportsDeveloperRole: false
supportsReasoningEffort: false
supportsStore: false
maxTokensField: max_tokens
metadataGeneration:
disableThinking: true
Controllare inoltre:
profile: servereprojectDirectoryuguale al checkout reale;workspaceRepositoryuguale alla riga PSD della tabella iniziale;authentication.configDirectorynella nuova directory canonica;authentication.runtimeProjectionin una directory separata, conuid: 10001egid: 10001;- un solo override Git SSH;
- nessun riferimento a vecchi
deploy/pi/models.json,deploy/pi/settings.jsono model metadata nel workspace; - nessun overlay session PostgreSQL salvo approvazione separata.
La proiezione Compose dell'auth runtime è automatica: non aggiungere manualmente
deploy/compose.auth-runtime-projection.yaml agli override. Se un endpoint di modello non è
raggiungibile dal server, fermarsi e chiedere quale provider mantenere; non cambiare silenziosamente
i default.
Aggiornare l'env operatore usando deploy/env/server.env.example come checklist. Devono essere
valorizzati almeno i percorsi THT_CATALOG_RUNTIME_PASSWORD_SOURCE,
THT_CATALOG_MIGRATOR_PASSWORD_SOURCE, THT_DATA_ROOT, THT_PI_STATE_ROOT,
THT_WORKSPACE_REGISTRY_ROOT, THT_BACKUP_ROOT, le sorgenti auth/Git e le porte. Le directory
persistenti della nuova installation non devono coincidere accidentalmente con quelle legacy.
Esito richiesto: descriptor e env contengono soltanto configurazione non segreta, puntano ai secret file protetti e descrivono esattamente workspace, auth e modelli approvati.
7. Verificare Authentik senza ricrearlo
Se Public URL resta invariato, non creare una seconda applicazione/provider in Authentik. Il provider esistente deve avere:
- callback esatta
<PUBLIC_URL>/api/auth/oidc/callback; - scope
openid profile email; - claim
groupsnon vuoto come array JSON; - gruppi applicativi attesi, normalmente
TOT UserseTOT Admin; - token del service account con sola lettura dei gruppi.
Configurare o rigenerare soltanto la configurazione canonica della nuova installation:
sudo tht --installation "$THTII_NEW_INSTALLATION" auth configure \
--mode oidc \
--public-url "$THTII_PUBLIC_URL" \
--issuer "$THTII_AUTH_ISSUER" \
--client-id "$THTII_AUTH_CLIENT_ID" \
--authentik-base-url "$THTII_AUTHENTIK_URL" \
--user-group 'TOT Users' \
--admin-group 'TOT Admin'
tht --installation "$THTII_NEW_INSTALLATION" auth status --json
Il comando non riceve secret come argomenti: li risolve dai riferimenti nel secret bundle. La nuova
directory auth-state può partire vuota. Le vecchie sessioni browser non devono essere migrate e
gli utenti dovranno autenticarsi di nuovo dopo il cutover.
Esito richiesto: lo status redatto indica mode: oidc, URL e gruppi corretti; nessun secret è
presente in YAML, argomenti, log o report.
8. Preflight e preparazione dei servizi interni
tht start rigenera le proiezioni e avvia i servizi, ma non esegue il job esplicito
catalog-migrate. Preparare quindi immagini e servizi interni con la stessa identità Compose della
nuova installation mentre il vecchio frontend/core sono ancora attivi.
Per prima cosa validare il descriptor e il render Compose:
tht --installation "$THTII_NEW_INSTALLATION" update --check-only
Questo comando carica e valida il descriptor; dopo la modifica del modelCatalog, la proiezione
generata da setup resta intenzionalmente precedente fino a tht start. Non usare doctor come
gate in questo momento: i servizi sono fermi e il suo controllo di drift deve ancora fallire. Il
gate completo viene eseguito al passo 10, dopo che start ha rigenerato la proiezione.
Calcolare il Compose project name con la stessa regola del CLI e costruire l'array dei file. Questo
blocco è esatto per il descriptor atteso, che ha il solo override Git SSH. Se nel descriptor ci sono
altri override approvati, inserirli nello stesso ordine subito dopo compose.git-ssh.yaml; non
ometterli e non aggiungere l'overlay sessioni per comodità.
THTII_NEW_INSTALLATION=$(realpath "$THTII_NEW_INSTALLATION")
THTII_INSTALL_DIR=$(dirname "$THTII_NEW_INSTALLATION")
THTII_COMPOSE_PROJECT="thothii-$(printf '%s' "$THTII_NEW_INSTALLATION" | sha256sum | cut -c1-12)"
THTII_COMPOSE=(
docker compose
--project-name "$THTII_COMPOSE_PROJECT"
--project-directory "$THTII_REPO"
--env-file "$THTII_NEW_ENV"
-f "$THTII_REPO/compose.yaml"
-f "$THTII_REPO/deploy/compose.server.yaml"
-f "$THTII_REPO/deploy/compose.git-ssh.yaml"
-f "$THTII_INSTALL_DIR/generated/compose.models.yaml"
-f "$THTII_REPO/deploy/compose.auth-runtime-projection.yaml"
)
"${THTII_COMPOSE[@]}" config --quiet
Non stampare il render completo. Costruire le immagini e avviare soltanto i servizi interni privi di porte host:
"${THTII_COMPOSE[@]}" build core frontend
"${THTII_COMPOSE[@]}" up --detach catalog-db qdrant embedding
"${THTII_COMPOSE[@]}" run --rm catalog-migrate
"${THTII_COMPOSE[@]}" run --rm embedding-model-init
"${THTII_COMPOSE[@]}" ps --all
Il comando catalog-migrate deve terminare con exit 0 prima che core venga avviato. Anche
embedding-model-init deve terminare con exit 0 e lasciare il modello nel volume della nuova
installation. Questi comandi non pubblicano la nuova applicazione e non toccano i volumi legacy.
Confermare inoltre che il server abbia accesso in uscita necessario al primo pull del modello
Ollama e spazio sufficiente per embedding-models. Qdrant e catalog-db devono restare sulla rete
Compose privata, senza porte host pubblicate.
L'overlay NER deploy/compose.sensitivity-ner.yaml non è richiesto per il primo avvio. La policy
deterministica funziona senza NER. Abilitare il modello CPU soltanto con la procedura e i gate in
Analisi locale della sensibilità.
Esito richiesto: render Compose valido, immagini costruite, catalog-db healthy, migrazione exit
0, Qdrant/Ollama healthy e modello embedding inizializzato; core e frontend nuovi sono ancora
fermi.
9. Cutover controllato
Gate operatore B — finestra di manutenzione
Presentare prima:
- hash release, descriptor nuovo e risultato del preflight;
- comando esatto per fermare e riavviare il vecchio stack;
- comando di rollback, image ID conservati e durata stimata;
- porte e route del reverse proxy che resteranno invariate o verranno cambiate.
Dopo approvazione, bloccare nuove attività applicative e fermare solo lo stack legacy con il comando registrato al passo 1. Non rimuoverne container o volumi. Avviare quindi la nuova installation:
tht --installation "$THTII_NEW_INSTALLATION" start
Il primo avvio deve:
- rigenerare le proiezioni del model catalog aggiornato;
- riutilizzare le immagini costruite e il catalogo già migrato al passo 8;
- confermare healthy
catalog-dbe Qdrant; - avviare Ollama ed eseguire/verificare
embedding-model-initperqwen3-embedding:0.6b; - avviare
coresoltanto dopo le dipendenze richieste; - avviare
frontendsulla bind address prevista per il reverse proxy.
Non interrompere il primo pull perché è lento se log e avanzamento restano regolari. In caso di errore, raccogliere soltanto i log sanitizzati:
tht --installation "$THTII_NEW_INSTALLATION" status
tht --installation "$THTII_NEW_INSTALLATION" logs
embedding-model-init è one-shot: exited (0) è lo stato corretto, non un guasto. Il job
catalog-migrate è stato eseguito con run --rm, quindi fa fede l'exit 0 registrato al passo 8.
Qualsiasi exit diverso da zero blocca il cutover.
Esito richiesto: servizi persistenti healthy/running, job one-shot terminati con exit 0 e reverse proxy diretto alla nuova UI; i volumi legacy esistono ancora.
10. Verificare autenticazione e runtime
Eseguire:
tht --installation "$THTII_NEW_INSTALLATION" status
tht --installation "$THTII_NEW_INSTALLATION" doctor --json
tht --installation "$THTII_NEW_INSTALLATION" auth status --json
tht --installation "$THTII_NEW_INSTALLATION" auth check
tht --installation "$THTII_NEW_INSTALLATION" pi test
Dal browser verificare:
- redirect ad Authentik e ritorno alla callback corretta;
- login di un membro
TOT Users; - accesso amministrativo soltanto a un membro
TOT Admin; - logout e nuova autenticazione;
- assenza di loop OIDC, cookie error o
502del reverse proxy.
È previsto che le sessioni browser precedenti non siano più valide. Non è previsto modificare issuer, client o gruppi per aggirare un errore: diagnosticare prima callback, claim e secret refs.
Esito richiesto: doctor, auth check e pi test passano e i due ruoli Authentik sono mappati
correttamente.
11. Ripuntare e materializzare il workspace PSD
Il vecchio workspace runtime non è una sorgente da copiare. La nuova installation deve clonare e validare il repository Git approvato:
git@github.com:mptyl/tht-workspace-psd.git, branch main, access ssh
Nella UI amministrativa, nell'ordine:
- usare Update workspace repository per fetch/clone e validazione;
- selezionare il workspace PSD; l'ID atteso è
psd-clinical, ma confermarlo dal catalogothoth-workspaces.yamlanziché forzarlo; - usare Validate workspace source;
- aprire Database Management e creare/aggiornare il database del workspace;
- configurare il binding
postgres_directcon gli stessi endpoint, ruolo read-only e CA già approvati sul server; reinserire la password nel secret store write-only, non nel repository; - eseguire Test workspace connections;
- eseguire una sincronizzazione completa dello schema nel nuovo catalogo;
- selezionare quel workspace come workspace globale dell'installation.
Poi verificare e materializzare con il CLI:
tht --installation "$THTII_NEW_INSTALLATION" workspace inspect \
--workspace psd-clinical --json
tht --installation "$THTII_NEW_INSTALLATION" workspace preprocess run \
--workspace psd-clinical --json
Se il preprocessing fallisce, correggere il Catalog o la configurazione e rilanciare lo stesso comando dall'inizio: non esistono resume o rollback. Il comando completo materializza LSH e vettori di schema dal Metadata Catalog e ricostruisce la slice Evidence. Le nuove sessioni pinzano la revisione Git attiva del workspace.
Non copiare nel nuovo descriptor i legacy harness/workspaces/*.yaml come catalogo authored e non
trasferire vecchi indici vettoriali incompatibili. Il repository workspace schema v4 definisce
identità ed Evidence; database, metadati, binding, segreti e selezione attiva restano locali
all'installation.
Esito richiesto: workspace inspect mostra repository, branch e revisione PSD corretti; test
DWH diretto, schema sync e preprocess completo terminano con successo; Qdrant contiene la nuova
generazione Evidence.
12. Accettazione finale
Prima di dichiarare concluso l'upgrade, consegnare una checklist con evidenze redatte:
git rev-parse HEADuguale alla release approvata e worktree pulito;originuguale al Gitea ThothII e workspace remote uguale al GitHub PSD;tht doctor --json,auth checkepi testsenza errori;catalog-db, Qdrant, Ollama, core e frontend healthy;catalog-migrateedembedding-model-initterminati con exit 0;- login Authentik utente/admin verificato;
- binding DWH diretto read-only verificato;
- catalogo sincronizzato e preprocess workspace completato;
- una nuova sessione di prova crea artifact e usa la revisione workspace attiva;
- backup, checksum, rollback branch e immagini legacy ancora disponibili;
- nessun secret aggiunto al repository o ai log condivisi.
Gate operatore C — fine osservazione
Non rimuovere ancora stack, immagini, volumi o backup legacy. La loro eliminazione è un'attività successiva e distruttiva, autorizzata soltanto dopo un periodo di osservazione e un backup completo della nuova installazione che includa esplicitamente anche il catalogo PostgreSQL.
Rollback
Eseguire il rollback se il nuovo stack non diventa healthy, Authentik non completa il login, il DWH diretto non passa il test o il workspace non si materializza entro la finestra approvata.
-
Raccogliere
statuse log sanitizzati della nuova installation. -
Fermarla senza volumi:
tht --installation "$THTII_NEW_INSTALLATION" stop -
Ripristinare i tag immagine legacy dagli image ID/tag conservati se il nuovo build li ha sostituiti.
-
Riportare il checkout al rollback branch soltanto se il comando legacy legge file dal checkout:
cd "$THTII_REPO" git switch rollback/server-pre-v2-YYYYMMDD -
Riavviare il vecchio stack con il comando esatto registrato al passo 1.
-
Ripristinare la route reverse proxy precedente se era cambiata.
-
Verificare vecchia UI, Authentik e DWH; non montare i nuovi volumi nel vecchio stack.
-
Lasciare intatti i volumi della nuova installation per l'analisi post-mortem.
Esito richiesto: il servizio precedente è nuovamente disponibile con i suoi dati originali e la nuova installazione è ferma ma ispezionabile.