Closes #578. Rewrites the user file library save-mode description in the English database.md and architecture.md guides (independent-new by default, parent-linked on overwrite) and updates all 20 translated copies of each, with i18n_source_hash re-stamped so the parity gate stays green.
7.3 KiB
description, i18n_source_hash, i18n_provenance, i18n_output_hash
| description | i18n_source_hash | i18n_provenance | i18n_output_hash |
|---|---|---|---|
| Schema del database PostgreSQL, tabelle, migrazioni e procedure di backup per SnapOtter. | 50d5d4f220cf | human | 6498644e25e3 |
Database
SnapOtter usa PostgreSQL 17 con Drizzle ORM (pg-core / node-postgres) per la persistenza dei dati. Lo schema è definito in apps/api/src/db/schema.ts.
La connessione è configurata tramite la variabile d'ambiente DATABASE_URL (predefinita postgres://snapotter:snapotter@postgres:5432/snapotter). In Docker Compose, il container Postgres memorizza i suoi dati nel volume denominato SnapOtter-pgdata.
Tabelle
users
Memorizza gli account utente. Creata automaticamente al primo avvio da DEFAULT_USERNAME e DEFAULT_PASSWORD.
| Colonna | Tipo | Note |
|---|---|---|
id |
uuid | Chiave primaria |
username |
varchar | Univoco, obbligatorio |
passwordHash |
varchar | Hash scrypt |
role |
varchar | admin, editor o user |
mustChangePassword |
boolean | Flag di reimpostazione forzata della password |
createdAt |
timestamp | Data di creazione |
updatedAt |
timestamp | Data dell'ultimo aggiornamento |
sessions
Sessioni di login attive. Ogni riga associa un token di sessione a un utente.
| Colonna | Tipo | Note |
|---|---|---|
id |
varchar | Chiave primaria (token di sessione) |
userId |
uuid | Chiave esterna verso users.id |
expiresAt |
timestamp | Data di scadenza |
createdAt |
timestamp | Data di creazione |
teams
Gruppi per organizzare gli utenti. Gli amministratori possono assegnare gli utenti ai team.
| Colonna | Tipo | Descrizione |
|---|---|---|
id |
uuid | Chiave primaria |
name |
varchar (univoco, max 50 caratteri) | Nome del team |
createdAt |
timestamp | Data di creazione |
api_keys
Chiavi API per l'accesso programmatico. La chiave grezza viene mostrata una sola volta alla creazione; viene memorizzato solo l'hash.
| Colonna | Tipo | Note |
|---|---|---|
id |
uuid | Chiave primaria |
userId |
uuid | Chiave esterna verso users.id |
keyHash |
varchar | Hash scrypt della chiave |
name |
varchar | Etichetta fornita dall'utente |
createdAt |
timestamp | Data di creazione |
lastUsedAt |
timestamp | Aggiornata a ogni richiesta autenticata |
Le chiavi hanno il prefisso si_ seguito da 96 caratteri esadecimali (48 byte casuali).
pipelines
Catene di strumenti salvate che gli utenti creano nell'interfaccia.
| Colonna | Tipo | Note |
|---|---|---|
id |
uuid | Chiave primaria |
name |
varchar | Nome della pipeline |
description |
varchar | Descrizione facoltativa |
steps |
jsonb | Array di oggetti { toolId, settings } |
createdAt |
timestamp | Data di creazione |
user_files
Libreria di file persistente. Per impostazione predefinita, una modifica salvata viene inserita come riga radice indipendente ("salva come nuovo": version 1, parentId null, così l'originale resta elencato), oppure come versione collegata al genitore quando sovrascrivi l'originale (parentId impostato, version incrementata, sostituendolo). La colonna toolChain registra gli strumenti applicati.
| Colonna | Tipo | Descrizione |
|---|---|---|
id |
uuid | Chiave primaria |
userId |
uuid | FK verso users (CASCADE DELETE) |
originalName |
varchar | Nome del file di caricamento originale |
storedName |
varchar | Nome del file su disco |
mimeType |
varchar | Tipo MIME |
size |
integer | Dimensione del file in byte |
width |
integer | Larghezza dell'immagine in px |
height |
integer | Altezza dell'immagine in px |
version |
integer | Numero di versione (1 = originale) |
parentId |
uuid o null | FK verso user_files (versione genitore) |
toolChain |
jsonb | ID degli strumenti applicati in ordine per produrre questa versione |
createdAt |
timestamp | Data di creazione |
jobs
Traccia i job di elaborazione per la segnalazione dell'avanzamento e la pulizia.
| Colonna | Tipo | Note |
|---|---|---|
id |
uuid | Chiave primaria |
type |
varchar | Identificatore dello strumento o della pipeline |
status |
varchar | queued, processing, completed o failed |
progress |
real | Frazione 0.0-1.0 |
inputFiles |
jsonb | Array dei percorsi dei file di input |
outputPath |
varchar | Percorso del file risultato |
settings |
jsonb | Impostazioni dello strumento utilizzate |
error |
varchar | Messaggio di errore in caso di fallimento |
createdAt |
timestamp | Data di creazione |
completedAt |
timestamp | Data di completamento |
settings
Archivio chiave-valore per le impostazioni a livello di server che gli amministratori possono modificare dall'interfaccia.
| Colonna | Tipo | Note |
|---|---|---|
key |
varchar | Chiave primaria |
value |
varchar | Valore dell'impostazione |
updatedAt |
timestamp | Data dell'ultimo aggiornamento |
roles
Ruoli personalizzati con permessi granulari.
| Colonna | Tipo | Note |
|---|---|---|
id |
uuid | Chiave primaria |
name |
varchar | Nome univoco del ruolo |
description |
varchar | Descrizione facoltativa |
permissions |
jsonb | Array di stringhe di permesso |
createdAt |
timestamp | Data di creazione |
audit_log
Registro delle azioni rilevanti per la sicurezza.
| Colonna | Tipo | Note |
|---|---|---|
id |
uuid | Chiave primaria |
userId |
uuid | FK verso users |
action |
varchar | Tipo di azione |
details |
jsonb | Dati specifici dell'azione |
createdAt |
timestamp | Data dell'azione |
Migrazioni
Drizzle gestisce le migrazioni dello schema. I file di migrazione risiedono in apps/api/drizzle/. Durante lo sviluppo:
cd apps/api
npx drizzle-kit generate # generate a migration from schema changes
npx drizzle-kit migrate # apply pending migrations
In produzione, le migrazioni in sospeso vengono applicate automaticamente all'avvio.
Backup e ripristino
Il database relazionale risiede nel volume SnapOtter-pgdata del container Postgres, non nel volume /data dell'app.
Opzione 1: pg_dump (consigliata)
# Dump the database while the stack is running
docker exec SnapOtter-postgres pg_dump -U snapotter snapotter > backup.sql
# Restore into a fresh database
cat backup.sql | docker exec -i SnapOtter-postgres psql -U snapotter snapotter
Opzione 2: Snapshot del volume
# Stop the stack, then snapshot the pgdata volume
docker compose down
docker run --rm -v SnapOtter-pgdata:/data -v $(pwd)/backup:/backup \
alpine tar czf /backup/snapotter-pgdata.tar.gz -C /data .
Migrazione dalla 1.x (SQLite)
L'aggiornamento da SnapOtter 1.x ha una guida dedicata: vedi Aggiornamento dalla 1.x alla 2.0. In breve, riutilizza il tuo volume /data esistente e la 2.0 rileva e importa automaticamente /data/snapotter.db al primo avvio (oppure imposta SQLITE_MIGRATE_PATH per puntarvi esplicitamente). Esegui prima il backup dell'intero volume /data, non solo di snapotter.db: la 1.x usa la modalità WAL di SQLite, quindi un container arrestato lascia spesso la maggior parte dei suoi dati in snapotter.db-wal accanto a un snapotter.db quasi vuoto.