696 lines
37 KiB
Markdown
696 lines
37 KiB
Markdown
# Metadata Catalog di ThothII: ricognizione ThothAI e percorso incrementale
|
|
|
|
Data: 2026-08-26; aggiornato 2026-08-27
|
|
Stato: ricognizione e progettazione completate; navigazione, CRUD Workspace Database, Catalog
|
|
Table, Catalog Column, Catalog Relationship e sincronizzazione durevole dello schema implementati
|
|
il 2026-08-27. Generazione AI e integrazione con il workflow core restano negli step successivi.
|
|
|
|
## 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 ha aggiunto l'accesso dalla sidebar; il
|
|
secondo ha sostituito la superficie vuota con il CRUD di configurazione, il PostgreSQL interno e i
|
|
test di connessione; gli step successivi hanno aggiunto navigazione gerarchica, colonne, relazioni
|
|
fisiche e sincronizzazione durevole dell'intero schema. Non introduce ancora generazione AI o
|
|
integrazione 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 Database appartiene a un solo workspace tramite un `workspace_id` obbligatorio e
|
|
univoco; un workspace può avere al massimo un Workspace Database. Poiché i workspace non sono
|
|
righe del catalogo PostgreSQL, l'associazione è un riferimento logico validato contro
|
|
`thoth-workspaces.yaml`, non una foreign key SQL.
|
|
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.
|
|
10. La compatibilità con il modello ThothAI è semantica, non una copia letterale: configurazione e
|
|
contenuti semantici sono campi relazionali mutabili, mentre identità e appartenenza della
|
|
struttura fisica derivano dall'introspezione; i segreti restano nel secret store e lo stato dei
|
|
job non viene mescolato ai dati amministrativi.
|
|
11. Il CRUD amministra il Metadata Catalog e non esegue DDL sul database esterno, che resta
|
|
read-only.
|
|
12. La prima versione supporta PostgreSQL; il confine di introspezione dovrà permettere di
|
|
aggiungere altri dialetti senza cambiare il modello del catalogo.
|
|
13. I segreti dei Workspace Database riusano il secret store cifrato di ThothII. Il catalogo
|
|
conserva riferimenti ai segreti e nessuna API, esportazione o log ne restituisce i valori.
|
|
14. La UI usa AG Grid Community per la lista master e un pannello React separato per il dettaglio;
|
|
non dipende dalle funzionalità master-detail di AG Grid Enterprise.
|
|
15. Un Workspace Database il cui `workspace_id` scompare dal catalogo YAML non viene cancellato
|
|
automaticamente: diventa orphaned e può soltanto essere recuperato, riassegnato o eliminato
|
|
esplicitamente da un amministratore.
|
|
16. La prima vertical slice gestisce configurazione del Workspace Database, riferimenti ai segreti,
|
|
test di connessione e stato. La seconda gestisce le Catalog Table: la collezione e i nomi sono
|
|
controllati dall'introspezione, mentre la descrizione curata è modificabile. Le slice successive
|
|
hanno aggiunto Catalog Column, Catalog Relationship e sincronizzazione durevole dello schema.
|
|
17. Il modello non conserva il `name` libero di ThothAI: nome e ID visualizzati appartengono al
|
|
workspace YAML, mentre `database_name` identifica il database PostgreSQL esterno.
|
|
18. Database management supporta i tre trasporti già riconosciuti da ThothII: `postgres_direct`,
|
|
`rest_api` e `ssh_tunnel`. PSD rimane un solo Workspace Database: usa la connessione diretta sul
|
|
server e l'endpoint REST in locale tramite una Database Binding specifica dell'installazione.
|
|
Questo supporto non abilita automaticamente `ssh_tunnel` nel runtime NL→SQL.
|
|
19. Una configurazione può essere salvata prima di una connessione riuscita. Il test separato
|
|
produce uno stato `untested`, `reachable` o `failed`; attivazione e introspezione richiedono uno
|
|
stato raggiungibile.
|
|
20. Il CRUD e il test di connessione richiedono `database.manage`; inserimento e sostituzione dei
|
|
segreti continuano a richiedere `workspace.secrets.manage`.
|
|
21. Il Workspace Database e il modo di raggiungerlo sono entità distinte. Ogni catalogo di
|
|
installazione conserva una sola Database Binding attiva per workspace: PSD usa `rest_api` in
|
|
locale e `postgres_direct` sul server senza duplicare il Workspace Database.
|
|
22. Nel modello finale il Metadata Catalog è autorevole per engine, `database_name`, schema,
|
|
capacità e binding. Lo YAML resta autorevole per identità e contenuti del workspace; i campi
|
|
DWH correnti saranno importati, confrontati e rimossi soltanto durante un cutover esplicito.
|
|
23. La lista master è l'unione fra workspace YAML e record del catalogo: mostra workspace
|
|
`unconfigured`, database configurati e record `orphaned`.
|
|
24. Ogni introspezione registra le capability disponibili. Una capability `unavailable` non viene
|
|
rappresentata come una collezione osservata ma vuota; REST può completare con successo anche
|
|
quando indici o enum non sono supportati.
|
|
25. Il Metadata Catalog non introduce snapshot, draft o pubblicazioni. Configurazione e contenuti
|
|
semantici, inclusi quelli futuri generati dall'AI, sono normali campi modificabili; la struttura
|
|
osservata cambia soltanto con una sincronizzazione esplicita.
|
|
26. Il normale Delete elimina realmente il Workspace Database, la Database Binding e i relativi
|
|
record catalogo e segreti. Non modifica il DWH esterno né il repository YAML; il workspace torna
|
|
visibile nella lista master come `unconfigured`.
|
|
27. La prima versione gestisce un solo schema obbligatorio per Workspace Database, identificato
|
|
dalla coppia `database_name + schema`; per PSD la coppia è `postgres + datawarehouse`.
|
|
28. I record mantengono soltanto `created_at`, `updated_at` e un contatore `version` per optimistic
|
|
concurrency. Non esistono storico delle revisioni, rollback o audit applicativo delle modifiche.
|
|
29. `workspace_databases` conserva soltanto UUID, `workspace_id` unique, engine, `database_name`,
|
|
schema, timestamp e version. Il nome visualizzato appartiene al workspace YAML.
|
|
30. Ogni Workspace Database ha al massimo una riga `database_bindings`. Una singola tabella usa
|
|
check constraint dipendenti da `transport` per i campi direct, REST e SSH; non esiste un flag
|
|
`active`, perché ciascuna installazione conserva una sola binding.
|
|
31. `rest_api` configura il Thoth REST Connector tipizzato: base URL, autenticazione e TLS sono dati
|
|
della binding, mentre path RPC e shape delle risposte appartengono al contratto applicativo e non
|
|
sono liberamente configurabili.
|
|
32. Il test connessione usa soltanto una configurazione già salvata ed è associato alla sua
|
|
`version`. Ogni modifica della binding o dei segreti invalida il risultato precedente e riporta
|
|
lo stato a `untested`.
|
|
33. Password, API key e chiavi sono write-only: l'API espone soltanto `configured`, un campo vuoto
|
|
conserva il valore esistente e la sostituzione è un'azione esplicita. Delete rimuove anche i
|
|
segreti associati.
|
|
34. La pagina usa AG Grid come master e un form React come detail, con sezioni Database, Connection
|
|
e TLS/SSH condizionali. Non esiste un'azione globale `Add database`: ogni riga `unconfigured`
|
|
offre `Configure catalog`, apre il form già vincolato a quello specifico workspace YAML e crea il
|
|
record soltanto al Save; `workspace_id` non è selezionabile né modificabile.
|
|
35. La grid mostra separatamente revisione/Evidence del workspace, binding runtime NL→SQL e
|
|
configurazione del Metadata Catalog, oltre a database, schema, endpoint e ultimo aggiornamento.
|
|
Su schermi piccoli il dettaglio occupa il pannello completo. Il cambio riga con modifiche non
|
|
salvate e Delete richiedono conferma, senza conferma testuale tipizzata.
|
|
36. La Database Binding conserva `connection_status`, `tested_version`, `last_tested_at`, un codice
|
|
errore e un messaggio breve sanificato. Non conserva stack trace, DSN, credenziali o output grezzo
|
|
del driver.
|
|
37. Le API vivono sotto `/api/catalog`: list/create di `/databases`, get/patch/delete di
|
|
`/databases/:id`, sostituzione dei segreti sotto `/databases/:id/secrets`, test connessione sotto
|
|
`/databases/:id/test` e list/patch/sync delle tabelle sotto `/databases/:id/tables`.
|
|
38. `GET /api/catalog/databases` restituisce l'intera master list unificata; AG Grid Community applica
|
|
client-side ricerca, filtri e ordinamento. La prima versione non introduce paginazione server o
|
|
funzionalità AG Grid Enterprise.
|
|
39. Il Metadata Catalog vive nello stesso processo Fastify come modulo isolato con repository,
|
|
service, route, diagnostica e readiness proprie. L'indisponibilità del catalogo non modifica
|
|
sessioni, SSE o health del core e non giustifica ancora un microservizio separato.
|
|
40. Il backend mantiene `pg@8.22.0` e aggiunge `kysely@0.29.5` per query e transazioni tipizzate. Le
|
|
migrazioni Kysely sono timestampate, compilate con il backend ed eseguite da un comando
|
|
`catalog:migrate` separato; l'applicazione non migra automaticamente il database all'avvio.
|
|
41. Lo stack aggiunge un servizio interno `catalog-db` con volume persistente, ruolo runtime DML,
|
|
ruolo migrator DDL e job one-shot `catalog-migrate`. Un catalogo indisponibile produce 503 sulle
|
|
sole route catalogo.
|
|
42. La prima vertical slice è amministrativa: scrive il catalogo ma non cambia ancora il runtime di
|
|
sessioni e workflow, che continua a usare YAML e binding correnti fino al cutover esplicito.
|
|
43. `Configure` precompila senza salvare engine, database e schema dal descriptor e i dati non
|
|
sensibili dalla binding effettiva. L'amministratore verifica, inserisce i segreti e salva; non
|
|
esiste importazione silenziosa.
|
|
44. Unit e route test usano un repository fake; una suite PostgreSQL Testcontainers separata verifica
|
|
migrazioni, constraint, transazioni, optimistic concurrency e cascade. SQLite ed emulatori non
|
|
sono sostituti ammessi per questi test.
|
|
45. La navigazione delle entità catalogo è gerarchica e senza scorciatoie globali: `Databases →
|
|
Database → Overview | Tables → Table`. Non esistono una voce globale Tables, un filtro globale
|
|
Database o una preselezione implicita; Columns continuerà sotto Table e Relationships sotto
|
|
Database.
|
|
46. Una Catalog Table conserva nome fisico, `source_comment`, descrizione curata nullable,
|
|
`generated_description` nullable per lo step AI futuro, version e timestamp. La UI mostra come
|
|
tre campi indipendenti senza fallback visivo: source comment read-only, generated description
|
|
modificabile e description modificabile. I valori null restano celle e controlli vuoti.
|
|
47. Le Catalog Table non possono essere aggiunte o rinominate manualmente. Un amministratore può
|
|
però ripulire esplicitamente le proiezioni nel Metadata Catalog senza modificare il database
|
|
esterno; `Sync tables` legge le tabelle PostgreSQL ordinarie e partizionate dello schema scelto,
|
|
mentre viste e materialized view sono escluse.
|
|
48. La sincronizzazione è esplicita. La scansione avviene fuori dalla transazione del catalogo; il
|
|
diff viene applicato atomicamente soltanto se la version del Workspace Database è ancora quella
|
|
sottoposta a scansione. Una scansione fallita non modifica il catalogo.
|
|
49. Tabelle nuove vengono create, i commenti sorgente vengono aggiornati e quelle non più osservate
|
|
vengono eliminate definitivamente. La rimozione di tabelle, colonne o relazioni richiede la
|
|
conferma dell'esatto piano distruttivo; se il secondo scan produce una fotografia differente,
|
|
l'applicazione richiede una nuova conferma.
|
|
50. Un rename fisico è intenzionalmente delete più create e perde i metadati curati. Le colonne e
|
|
relazioni dipendenti vengono eliminate in cascade insieme alla Catalog Table.
|
|
51. L'introspezione vive nel modulo catalogo Fastify dietro un adapter. PostgreSQL diretto e tunnel
|
|
SSH usano il catalogo `pg_catalog`; REST preferisce il contratto tipizzato
|
|
`POST /rpc/schema_snapshot` e, quando quell'RPC non è esposto, usa come fallback compatibile una
|
|
singola query read-only tramite `POST /rpc/run_query`. Entrambi i percorsi devono produrre la
|
|
stessa fotografia v1 stretta descritta in `docs/contracts/catalog-schema-snapshot.md`.
|
|
52. Test connessione e sincronizzazione sono serializzati per Workspace Database, hanno timeout e
|
|
richiedono che la binding nella version corrente abbia un test `reachable` prima di qualsiasi
|
|
Catalog Sync Run. La scansione asincrona ha un timeout separato, di default dieci minuti.
|
|
53. Il tunnel SSH usa OpenSSH in modalità stdio `-W`, chiave privata e passphrase opzionale dal
|
|
secret store, `known_hosts` obbligatorio, `StrictHostKeyChecking=yes`, agent e configurazione
|
|
globale disabilitati. Non è ammesso TOFU. TLS PostgreSQL con CA e server name resta verificato
|
|
anche attraverso il tunnel.
|
|
54. In questo slice `ssh_tunnel` è una binding supportata da Database management per Test connection
|
|
e Schema Sync. Il renderer e il runtime delle sessioni NL→SQL restano fuori scope e continuano a
|
|
rifiutarla finché non verrà deciso il relativo cutover.
|
|
55. I menu di azione a livello Workspace Database espongono separatamente `Synchronize tables`,
|
|
`Synchronize relationships` e `Synchronize all`. Su una selezione di
|
|
database lo scope scelto viene avviato per ogni database idoneo; non viene sostituito
|
|
implicitamente con una sincronizzazione completa.
|
|
56. Lo scope Columns è disponibile dalla grid Tables e limita la riconciliazione alle tabelle
|
|
selezionate; la pagina Columns non espone azioni di sincronizzazione. La grid Tables espone
|
|
`Synchronize columns` sulle tabelle selezionate.
|
|
|
|
## 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 processo ThothII implementato distingue 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` obbligatorio e unico sul Workspace Database, con esistenza validata contro il
|
|
catalogo YAML dal servizio applicativo;
|
|
- 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.
|
|
|
|
ThothII distingue i metadati di connessione dai riferimenti al secret store cifrato. 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.
|
|
|
|
La binding REST corrente richiede una verifica prima del cutover: il renderer emette
|
|
`ssl_ca_file`, mentre il modello Python espone `ssl_ca`; il percorso della CA privata potrebbe quindi
|
|
non essere consumato. PSD richiede TLS con CA privata in locale, perciò questo disallineamento deve
|
|
essere corretto e coperto da un test end-to-end prima di affidare il profilo REST al catalogo.
|
|
|
|
## 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
|
|
|
|
Progettazione della vertical slice completata: Workspace Database, Database Binding, singolo schema,
|
|
riferimenti al secret store, optimistic concurrency e capability per trasporto hanno contratti
|
|
espliciti. Configurazione e contenuti semantici restano mutabili; la struttura fisica osservata è
|
|
sincronizzata e non modificabile manualmente.
|
|
|
|
### Step 3: PostgreSQL interno e migrazioni
|
|
|
|
PostgreSQL interno con volume e ruoli runtime/migrator separati. Il modulo catalogo usa Kysely sopra
|
|
il driver `pg`; le migrazioni compilate vengono applicate soltanto dal comando `catalog:migrate` e
|
|
mai allo startup Fastify. Health, readiness e diagnostica restano dedicate; l'indisponibilità del
|
|
catalogo non cambia `core /health` e non interrompe 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
|
|
|
|
Workspace Database, Catalog Table, Catalog Column e Catalog Relationship sono implementati con
|
|
React/Vite e il design system ThothII.
|
|
La navigazione è gerarchica e locale al database (`Overview | Tables`), senza menu o filtri globali
|
|
per tipo di entità. La grid delle tabelle non offre Add o cancellazione della singola configurazione;
|
|
le selezioni espongono invece la pulizia esplicita dei metadati. Il dettaglio full-width mantiene
|
|
immutabili i fatti fisici e consente di modificare separatamente Description e Generated
|
|
Description. Colonne e relazioni seguono la stessa gerarchia: Columns appartiene al dettaglio
|
|
della tabella, Relationships al database. I valori descrittivi null sono mostrati come celle e
|
|
campi vuoti, senza fallback visivi o placeholder `Not set` che nascondano quale sorgente è
|
|
effettivamente valorizzata.
|
|
|
|
Le griglie che dispongono di azioni massive usano checkbox e una toolbar contestuale con conteggio,
|
|
menu `Actions` e cancellazione della selezione. La selezione identifica ID espliciti, può essere
|
|
accumulata attraverso i filtri e viene azzerata dopo successo, nuova sincronizzazione o uscita
|
|
dalla pagina; un'azione è all-or-nothing se un elemento non è idoneo. I menu a livello database
|
|
espongono gli scope fisici come azioni distinte: `Synchronize tables`, `Synchronize relationships`
|
|
e `Synchronize all`. La grid Tables espone invece `Synchronize columns` per le tabelle selezionate;
|
|
la pagina Columns non espone sincronizzazione. Le selezioni database aggiungono `Delete all tables` e
|
|
`Delete all relationships`; le selezioni tabelle aggiungono `Delete all columns` e `Delete all
|
|
relationships`. Queste operazioni sono atomiche, richiedono conferma e non modificano database
|
|
esterno, binding, configurazione o segreti. Test connection resta un'azione distinta; griglie senza
|
|
azioni non mostrano controlli di selezione inerti.
|
|
|
|
### Step 6: introspezione
|
|
|
|
Catalog Table, Catalog Column e Catalog Relationship sono implementate per PostgreSQL diretto,
|
|
Thoth REST Connector e tunnel SSH. La scansione read-only è separata dalla transazione; una
|
|
riconciliazione atomica crea, aggiorna i commenti sorgente ed elimina, dopo conferma, i fatti fisici
|
|
assenti senza rendere modificabile manualmente la struttura osservata. Gli scope autorevoli sono
|
|
Tables per database e Physical Relationships per database. Per Columns, `tableIds` vuoto include
|
|
tutte le Catalog Table correnti, mentre una lista di ID limita lo scope al sottoinsieme esplicito;
|
|
`Synchronize all` osserva tutti e tre gli scope in un unico snapshot e li riconcilia insieme. Tutti
|
|
gli scope sono eseguiti come Catalog Sync Run durevoli in background, non attraverso implementazioni
|
|
sincrone e asincrone separate. Un run che prevede cancellazioni conserva il diff, attende una
|
|
conferma esplicita e verifica nuovamente lo snapshot prima dell'applicazione; se la sorgente è
|
|
cambiata, invalida la conferma. Ogni applicazione è atomica e fail-closed: errori, timeout o
|
|
capability non disponibili non producono aggiornamenti parziali.
|
|
|
|
PK e FK devono essere visibili sulle Catalog Column senza duplicare le stringhe denormalizzate di
|
|
ThothAI. La posizione nella primary key è un fatto osservato della colonna; membership e conteggio
|
|
FK sono proiezioni derivate dalle Catalog Relationship e dalle loro coppie ordinate, aggiornate
|
|
nella stessa transazione di riconciliazione.
|
|
|
|
Ogni scope registra la versione della Database Binding osservata e l'istante dell'ultima
|
|
sincronizzazione. Una modifica della binding conserva il catalogo precedente ma lo marca stale;
|
|
solo un `Synchronize all` riuscito rende nuovamente corrente l'intero schema.
|
|
|
|
### Step 7: generazione AI dei metadati
|
|
|
|
Generated Description è una proposta distinta e modificabile: un revisore può correggerla prima
|
|
di consolidarla esplicitamente come Description. Lo slice AI dovrà decidere e implementare anche
|
|
alias semantici, descrizioni dei valori, sinonimi e concetti per tabelle e colonne, oltre alla
|
|
gestione esplicita di errori e output non validi. La generazione AI e l'azione di consolidamento non
|
|
appartengono allo slice di introspezione dello schema.
|
|
|
|
### 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.
|
|
Questo cutover è esplicitamente rinviato fino al completamento del database dei metadati. Il primo
|
|
gate successivo obbligatorio sarà valutare l'integrazione del Catalog Schema Snapshot con il
|
|
workflow core e lo schema-linking corrente; il rinvio non autorizza a dimenticare o assorbire
|
|
implicitamente il lavoro in altri slice.
|
|
|
|
### Step 10: operazioni e accettazione
|
|
|
|
Backup/restore reale, diagnostica, metriche, permessi definitivi, hardening degli export e
|
|
test di failure isolation fra catalogo e workflow. I Catalog Sync Run hanno un solo job attivo per
|
|
Workspace Database, sono concorrenti fra database diversi e usano un lock persistente. Un pannello
|
|
operativo non modale rimane visibile durante la navigazione del database, mostra fasi, contatori,
|
|
tempo trascorso e log sanitizzato via SSE con polling di fallback, e offre Confirm, Cancel e Retry
|
|
quando consentiti. Un restart marca `interrupted` i run rimasti attivi; il retry crea un nuovo run.
|
|
Le modifiche ai metadati restano consentite durante la scansione e sono preservate dall'applicazione.
|
|
Il worker gira inizialmente nello stesso servizio Fastify ma dietro un'interfaccia estraibile, con
|
|
coda, lease e heartbeat persistiti nel catalog-db. I riepiloghi dei run non scadono; gli eventi
|
|
dettagliati sono conservati per 30 giorni, mentre snapshot e diff completi vengono eliminati dopo
|
|
la conclusione lasciando conteggi, decisioni e una sintesi sanitizzata dell'esito.
|
|
|
|
## 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:
|
|
|
|
- lifecycle dei riferimenti ai segreti durante sostituzione e cancellazione;
|
|
- criteri per aggiungere dialetti successivi a PostgreSQL;
|
|
- criteri per un'eventuale estensione futura a più schemi per database;
|
|
- lifecycle e gestione amministrativa delle future Logical Relationship;
|
|
- alias semantici, descrizioni dei valori, sinonimi e concetti prodotti o assistiti dall'AI;
|
|
- 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.
|