feat(frontend): add database management surface

This commit is contained in:
Codex
2026-08-26 18:00:47 +02:00
parent 11f78c4467
commit a701b19a03
8 changed files with 708 additions and 8 deletions
@@ -0,0 +1,492 @@
# Metadata Catalog di ThothII: ricognizione ThothAI e percorso incrementale
Data: 2026-08-26
Stato: ricognizione completata; step 1 implementato; scelte tecnologiche degli step successivi
deliberatamente rinviate.
## Obiettivo
ThothII deve introdurre un contesto amministrativo separato, il **Metadata Catalog**, per gestire
il database associato a ciascun workspace, la sua struttura fisica introspezionata e i metadati
semantici oggi rappresentati da `schema/annotations.yaml`.
Il programma procede per step indipendenti. Il primo step aggiunge soltanto l'accesso dalla sidebar
destra a una superficie centrale vuota. Non introduce PostgreSQL, API CRUD, introspezione o
integrazioni con il workflow core.
Questa analisi usa come riferimento il working tree legacy osservato in
`Thoth/ThothAI`. Non è stato verificato che quel contenuto corrisponda a una release o a un tag
canonico; i percorsi e i comportamenti descrivono il sorgente disponibile il 2026-08-26.
## Decisioni già confermate
1. Ogni workspace è associato a un solo Workspace Database e ogni Workspace Database appartiene a
un solo workspace.
2. Il CRUD non crea né rinomina workspace. Identità e lista ordinata dei workspace restano
autorevoli in `thoth-workspaces.yaml`; il catalogo conserva il loro identificatore stabile.
3. La struttura fisica viene acquisita interrogando il database esterno tramite i dati di
connessione registrati per il Workspace Database.
4. I contenuti semantici equivalenti a `annotations.yaml` vengono generati con l'AI e conservati nel
PostgreSQL interno.
5. Per PSD è prevista l'importazione delle annotations esistenti. Gli altri database partiranno
dalla struttura introspezionata e genereranno i metadati semantici da zero.
6. `annotations.yaml` sarà sostituito anche come input del core in uno step futuro. Il repository è
in fase di test e non è richiesta la conservazione delle sessioni esistenti durante il cutover.
7. La gestione catalogo resta una superficie separata dal processo NL→SQL. La futura integrazione
deve essere esplicita e non deve modificare fasi, gate o semantica del workflow.
8. Il link iniziale è visibile agli utenti con `workspace.manage`, usa stato React locale e non
introduce un router.
9. La pagina iniziale è vuota, segue il tema, nasconde l'intera colonna core e non interrompe una
sessione live. Le azioni di apertura, resume o creazione sessione riportano al core.
## Correzione del modello mentale corrente
`schema/annotations.yaml` non contiene l'intero schema del database.
- `physical.yaml` è un artefatto derivato dall'introspezione. Contiene database, schema, timestamp,
tabelle, colonne, tipi, nullability, default, primary key, commenti sorgente, esempi, foreign key
fisiche e indici.
- `annotations.yaml` contiene metadati curati: descrizioni e concetti delle tabelle; descrizioni,
sinonimi, concetti, evidence, note e override `eligible` delle colonne; foreign key logiche.
- Il rendering M-Schema fonde questi due input. Le annotations prevalgono sui commenti sorgente e
le relazioni logiche vengono unite alle foreign key fisiche.
La sostituzione del solo file annotations non elimina automaticamente l'introspezione fisica. Il
nuovo catalogo dovrà conservare una distinzione esplicita fra fatti osservati nel database e
contenuto semantico modificabile.
## Architettura ThothII rilevante
### Autorità e revisionamento attuali
Il repository dei workspace contiene:
```text
thoth-workspaces.yaml
<workspace-id>/workspace.yaml
<workspace-id>/schema/annotations.yaml
<workspace-id>/evidence/**
```
Il backend legge descriptor e annotations allo stesso commit Git. Durante l'attivazione valida il
blob, lo copia atomicamente nello snapshot immutabile della revisione e registra commit, blob ID e
digest. Le nuove sessioni vengono legate a quella revisione; resume e SQL salvato riaprono lo stesso
snapshot.
Punti principali:
- `backend/src/workspaces/schema.ts`: descriptor v3 e singolo `dwh.database`/`dwh.schema`;
- `backend/src/workspaces/git-repository.ts`: lettura sicura del blob annotations al commit;
- `backend/src/workspaces/registry.ts`: validazione e attivazione atomica;
- `backend/src/workspaces/annotations-sync.ts`: materializzazione revision-qualified;
- `backend/src/workspaces/runtime-config-lease.ts`: binding dello snapshot al runtime;
- `harness/tht/mschema/models.py`: contratti `PhysicalSchema` e `Annotations`;
- `harness/tht/mschema/render.py`: fusione fisico/semantico;
- `harness/tht/cli/vector_cmd.py`: indicizzazione schema in Qdrant.
### Consumatori da preservare al cutover futuro
Le annotations incidono oggi su:
- override `eligible` prima del campionamento LSH;
- suggerimento, controllo e accettazione delle foreign key logiche;
- descrizioni, concetti e sinonimi dei record schema in Qdrant;
- retrieval delle tabelle e colonne candidate;
- rendering M-Schema usato dal gate F4 e dalla generazione SQL;
- digest della revisione accettata durante il preprocessing.
Il futuro cutover non potrà limitarsi a rimuovere il file: dovrà fornire al core lo stesso contenuto
effettivo, con un'identità coerente e test di equivalenza. Poiché non occorre preservare le sessioni
di test esistenti, non serve progettare compatibilità con i vecchi manifest, ma resta necessario
evitare letture parziali o semanticamente incoerenti.
## Inventario ThothAI
### Modelli legacy
I modelli sono definiti in `Thoth/ThothAI/backend/thoth_core/models.py`.
#### `SqlDb`
Campi di connessione osservati:
- `name`;
- `db_host`, `db_port`;
- `db_type`;
- `db_name`, `schema`;
- `user_name`, `password`;
- `db_mode`;
- configurazione SSH e Informix opzionale.
Il modello contiene anche scope, JSON dello scope, ERD, direttive, campi GDPR, collegamento a
`VectorDb` e numerosi campi di stato/task/log per lavori AI asincroni.
I tipi legacy dichiarati sono Informix, MariaDB, MySQL, Oracle, PostgreSQL, SQL Server e SQLite.
Questo elenco non costituisce automaticamente un requisito per ThothII: il core corrente supporta
PostgreSQL e l'estensione ad altri dialetti dovrà essere decisa separatamente.
#### `SqlTable`
- `name`;
- `description`;
- `generated_comment`;
- foreign key obbligatoria a `SqlDb`, con cancellazione cascade.
#### `SqlColumn`
- `original_column_name` e alias `column_name`;
- `data_format` normalizzato;
- `column_description`;
- `generated_comment`;
- `value_description`;
- stringhe denormalizzate `pk_field` e `fk_field`;
- foreign key obbligatoria a `SqlTable`, con cancellazione cascade.
#### `Relationship`
Contiene quattro foreign key obbligatorie:
- `source_table` e `source_column`;
- `target_table` e `target_column`.
Il form admin verifica che le tabelle appartengano allo stesso database e che ogni colonna
appartenga alla tabella selezionata. Il database non impone però gli stessi check.
#### `Workspace`
ThothAI usa `Workspace.sql_db` come foreign key nullable verso `SqlDb`: un workspace seleziona un
solo DB, mentre lo stesso DB può essere riusato da più workspace. ThothII adotterà invece una
relazione uno-a-uno: `workspace_id` deve essere unico nel catalogo.
### Lacune dei constraint legacy
Non risultano constraint database-level per:
- unicità del nome database nel workspace;
- unicità `(database, table name)`;
- unicità `(table, column name)`;
- unicità degli estremi di una relationship;
- appartenenza degli estremi della relationship allo stesso database;
- corrispondenza fra colonna e tabella dichiarata.
ThothII deve applicare queste invarianti sia nel database interno sia nel servizio applicativo. La
sola validazione del form non è sufficiente perché API, import e job la possono aggirare.
### Django Admin e UX da replicare concettualmente
ThothAI espone il CRUD tramite il Django Admin standard, registrato da
`backend/thoth_core/admin.py` e pubblicato su `/admin/`.
Capacità utili:
- lista database con ricerca per nome, host, tipo, database e schema;
- fieldset separati per identità, connessione, autenticazione, SSH e stato;
- lista tabelle filtrabile per database;
- lista colonne filtrabile in cascata per database e tabella;
- lista relazioni con estremi leggibili e filtri per database e tabelle;
- form relazione con dropdown dipendenti database → tabella → colonna;
- validazione degli estremi prima del salvataggio;
- azioni separate per test connessione, introspezione, import/export e generazione AI;
- azioni bulk sulle righe selezionate.
ThothII deve replicare i contratti di interazione e validazione, non il rendering server-side o i
template Django.
### Introspezione legacy
`Thoth/ThothAI/backend/thoth_core/dbmanagement.py` usa `thoth-dbmanager` per:
1. costruire l'adapter del dialetto;
2. acquisire tabelle;
3. acquisire e normalizzare colonne e tipi;
4. acquisire relazioni;
5. creare le eventuali colonne mancanti necessarie alle relazioni;
6. aggiornare i campi PK/FK denormalizzati.
Il comportamento è principalmente additivo: usa `get_or_create` o controlli `exists`, aggiorna
alcuni commenti, ma non riconcilia in modo completo rename, rimozioni o drift. Non va copiato così
com'è. Il futuro processo ThothII dovrà almeno distinguere scansione, differenze osservate e
applicazione della nuova snapshot.
### Generazione AI legacy
ThothAI dispone di azioni e workflow per:
- commenti delle tabelle;
- commenti delle colonne;
- scope del database;
- ERD Mermaid;
- documentazione del database;
- analisi GDPR.
Per il requisito attuale sono direttamente rilevanti descrizioni di tabelle e colonne, scope e
metadati semantici. ERD, documentazione aggregata e GDPR sono estensioni future, non prerequisiti
del CRUD iniziale.
La separazione `description`/`generated_comment` del legacy non offre versioning o approvazione
robusti. Nei passi successivi andrà deciso se l'output AI è una proposta revisionabile o diventa
immediatamente il valore editabile corrente.
### Import ed export legacy
ThothAI offre:
- CSV di database, tabelle, colonne e relazioni;
- export di struttura per workspace;
- import mediante `import_db_structure`;
- script SQL dei commenti per più dialetti;
- aggiornamento delle descrizioni colonna da CSV.
Il futuro import PSD dovrà leggere il contratto YAML corrente e convertirlo su chiavi naturali,
non riutilizzare gli ID numerici Django. Deve essere idempotente e produrre un report di elementi
creati, aggiornati, ignorati o non risolti.
## Comandi osservati in ThothAI
### Backend locale
Eseguiti da `Thoth/ThothAI/backend`:
```sh
uv sync
uv run python manage.py migrate
uv run python manage.py createsuperuser
uv run python manage.py runserver 8200
uv run pytest
```
Import catalogo legacy:
```sh
uv run python manage.py import_db_structure --source local
uv run python manage.py load_defaults --only-level 4 --source local
```
Test mirati rilevanti:
```sh
uv run pytest tests/test_relational_database_operations.py -v
uv run pytest tests/test_ssh_tunnel_configuration.py -v
```
### Stack Docker legacy
ThothAI dichiara `postgres:16-alpine` nel profilo `internal-db`, con volume persistente e
healthcheck `pg_isready`.
```sh
docker compose --profile internal-db up --build
```
Il wrapper legacy abilita lo stesso profilo quando `POSTGRES_INTERNAL=true`:
```sh
POSTGRES_INTERNAL=true ./docker-up.sh
```
Questi comandi documentano il riferimento osservato; non sono comandi di installazione per
ThothII.
## Cosa copiare in ThothII
### Parità necessaria
- gerarchia Workspace Database → Table → Column;
- relazione strutturale fra colonne sorgente e destinazione;
- navigazione e filtri dipendenti workspace/database/tabella;
- test di connessione separato dal salvataggio;
- introspezione esplicita e ripetibile;
- descrizioni generate dall'AI ma modificabili dall'utente;
- validazione cross-entity delle relazioni;
- azioni di import/export senza segreti;
- stato leggibile dei job lunghi;
- PostgreSQL interno persistente con migrazioni esplicite;
- test di CRUD, cardinalità, cascade/restrict, isolamento per workspace e idempotenza.
### Parità semantica con `annotations.yaml`
Il modello futuro deve poter rappresentare almeno:
- descrizione, concetti e note per tabella;
- descrizione, sinonimi, concetti, evidence, note ed `eligible` per colonna;
- foreign key logiche;
- distinzione fra commento fisico osservato e descrizione curata;
- provenienza del contenuto importato o generato.
L'eventuale esclusione di uno di questi campi deve essere una decisione esplicita perché cambia
rendering, retrieval, LSH o SQL generation.
### Vincoli minimi da progettare
- `workspace_id` unico sul Workspace Database;
- nome tabella unico nel database e schema appropriato;
- nome colonna unico nella tabella;
- relationship unica secondo il modello, anche per chiavi composite;
- estremi della relationship nello stesso Workspace Database;
- appartenenza certa della colonna alla tabella;
- mutazioni aggregate transazionali;
- gestione esplicita di concorrenza fra CRUD e introspezione.
## Cosa non copiare
- Django, Django Admin, Django ORM, DRF, template admin e frontend Next;
- modello Workspace legacy e condivisione dello stesso DB fra più workspace;
- password o passphrase come normali campi testuali;
- password incluse in CSV o export completi;
- token SSO inseriti nella query string;
- migrazioni generate automaticamente all'avvio;
- validazioni presenti soltanto nel form;
- `pk_field` e `fk_field` testuali come fonte di verità;
- duplicazione di tabella e colonna negli estremi senza constraint coerenti;
- introspezione additiva che non segnala rename, delete o drift;
- azioni admin che possono mostrare successo dopo output AI non valido;
- dipendenza del workflow core dalla disponibilità della UI o del PostgreSQL amministrativo.
## Aspetti di sicurezza da non ereditare
L'export legacy della struttura include username e password in chiaro. Il modello conserva inoltre
password, passphrase SSH e altri segreti in `CharField`; non è stata trovata cifratura applicativa,
nonostante un testo admin affermi il contrario.
Per ThothII resta da decidere nello step infrastrutturale quali dati di connessione siano normali
metadati e quali siano secret reference. In ogni caso:
- nessun endpoint o export deve restituire segreti;
- log ed errori devono sanificare DSN e credenziali;
- le credenziali di migrazione non devono essere disponibili al runtime CRUD;
- il catalogo non deve riusare credenziali del DWH, delle sessioni o di Qdrant;
- test connessione e introspezione devono usare timeout e privilegi read-only.
## Percorso incrementale
### Step 1: accesso alla superficie vuota
Implementato in questo worktree:
- pulsante `Database management` nella sidebar destra;
- visibilità legata a `workspace.manage`;
- superficie centrale React separata e vuota;
- nessun router, endpoint, fetch o stato catalogo;
- sessione e SSE conservati in background;
- ritorno al core tramite creazione, apertura o resume di una sessione;
- test frontend dedicati.
Comandi di verifica:
```sh
cd frontend
npx vitest run src/shell/AppShell.database-management.test.tsx
npx vitest run src/shell/AppShell.new-session.test.tsx \
src/shell/AppShell.session-target.test.tsx \
src/shell/AppShell.session-mgmt.test.tsx
npx tsc -b
```
### Step 2: contratto di dominio e schema relazionale
Da progettare con un nuovo round decisionale: campi, secret reference, dialetti supportati,
namespace/schema, snapshot fisiche, relazioni fisiche/logiche e lifecycle dell'output AI. Nessuna
tecnologia ORM o migration tool è stata scelta in questo documento.
### Step 3: PostgreSQL interno e migrazioni
Da progettare separatamente dal core: servizio, volume, ruoli runtime/migrator/backup, health e
readiness dedicati, backup/restore e diagnostica. La sua indisponibilità non dovrà cambiare
`core /health` o interrompere una sessione.
### Step 4: API CRUD
Contratti HTTP, autorizzazione, paginazione, filtri, errori, optimistic concurrency e transazioni.
Gli endpoint dovranno vivere sotto un namespace catalogo e non riutilizzare le route sessione.
### Step 5: UI CRUD
Liste e form per Workspace Database, tabelle, colonne e relazioni, costruiti con React/Vite e il
design system ThothII. La gerarchia e i filtri ThothAI sono il riferimento funzionale; Django Admin
non è il riferimento tecnologico o visuale.
### Step 6: introspezione
Connessione read-only, preview delle differenze, acquisizione di una Physical Schema Snapshot,
policy per rename/rimozioni e stato del job. Nessuna chiamata lunga dovrà mantenere aperta una
transazione CRUD.
### Step 7: generazione AI dei metadati
Generazione di descrizioni e altri campi equivalenti alle annotations, editing umano e gestione
esplicita di errori o output non validi. Approvazione/versioning saranno decisi in questo step.
### Step 8: migrazione PSD
Import idempotente delle annotations PSD, riconciliazione contro la struttura introspezionata,
report degli orfani e confronto semantico con il rendering corrente. Gli altri workspace non
ricevono import legacy.
### Step 9: sostituzione dell'input core
Rimuovere la dipendenza da `annotations.yaml` soltanto dopo avere un contratto equivalente,
test di rendering/search/Qdrant e una policy di disponibilità. Le sessioni di test esistenti
possono essere eliminate, ma le nuove sessioni non devono osservare aggiornamenti parziali.
### Step 10: operazioni e accettazione
Backup/restore reale, diagnostica, metriche, audit, permessi definitivi, hardening degli export e
test di failure isolation fra catalogo e workflow.
## Verifiche del core da conservare per il cutover
Comandi attuali rilevanti:
```sh
tht --installation <absolute>/thothii-installation.yaml workspace preprocess dwh \
--workspace <id> --json
tht --installation <absolute>/thothii-installation.yaml workspace schema suggest-fks \
--workspace <id> --json
tht --installation <absolute>/thothii-installation.yaml workspace schema check \
--workspace <id> --json
tht --installation <absolute>/thothii-installation.yaml workspace schema accept \
--workspace <id> --run <run-id> --yes --json
tht --installation <absolute>/thothii-installation.yaml workspace index-schema \
--workspace <id> --json
```
Suite che documentano il comportamento da preservare:
```sh
cd backend
npx vitest run test/workspaces-git-annotations.test.ts \
test/registry-annotations.test.ts \
test/annotations-sync.test.ts \
test/workspace-runtime-config-lease.test.ts \
test/workspace-preprocessing-service.test.ts
npx tsc --noEmit -p .
cd ../harness
.venv/bin/pytest -q \
tests/test_annotations_root.py \
tests/test_schema_fk_annotations.py \
tests/test_mschema_render.py \
tests/test_qdrant_cli_commands.py
```
Questi test non implicano che la futura implementazione debba continuare a usare file YAML.
Definiscono gli effetti semantici e le guardie da mantenere o sostituire consapevolmente.
## Decisioni rinviate
Le seguenti scelte non appartengono allo step 1:
- framework del servizio catalogo e libreria di accesso PostgreSQL;
- collocazione e protezione delle credenziali dei Workspace Database;
- supporto iniziale di dialetti diversi da PostgreSQL;
- uno o più schema namespace per database;
- policy di reconciliation per rename e delete;
- modello delle foreign key composite;
- distinzione persistente fra relationship fisiche e logiche;
- lifecycle draft/review/approval dell'output AI;
- versionamento, audit e rollback;
- formato e momento del cutover dal file al database interno;
- permission definitiva separata da `workspace.manage`.
Ognuna sarà affrontata nel relativo step, senza anticipare scelte tecnologiche nel presente
documento.