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.
6.8 KiB
description, i18n_source_hash, i18n_provenance, i18n_output_hash
| description | i18n_source_hash | i18n_provenance | i18n_output_hash |
|---|---|---|---|
| Skema database PostgreSQL, tabel, migrasi, dan prosedur pencadangan untuk SnapOtter. | 50d5d4f220cf | human | 8a963902d4f7 |
Database
SnapOtter menggunakan PostgreSQL 17 dengan Drizzle ORM (pg-core / node-postgres) untuk persistensi data. Skema didefinisikan di apps/api/src/db/schema.ts.
Koneksi dikonfigurasi melalui variabel lingkungan DATABASE_URL (default postgres://snapotter:snapotter@postgres:5432/snapotter). Di Docker Compose, kontainer Postgres menyimpan datanya di volume bernama SnapOtter-pgdata.
Tabel
users
Menyimpan akun pengguna. Dibuat otomatis pada saat pertama kali dijalankan dari DEFAULT_USERNAME dan DEFAULT_PASSWORD.
| Kolom | Tipe | Catatan |
|---|---|---|
id |
uuid | Primary key |
username |
varchar | Unik, wajib |
passwordHash |
varchar | hash scrypt |
role |
varchar | admin, editor, atau user |
mustChangePassword |
boolean | Flag reset kata sandi paksa |
createdAt |
timestamp | Waktu pembuatan |
updatedAt |
timestamp | Waktu pembaruan terakhir |
sessions
Sesi login aktif. Setiap baris mengaitkan token sesi ke seorang pengguna.
| Kolom | Tipe | Catatan |
|---|---|---|
id |
varchar | Primary key (token sesi) |
userId |
uuid | Foreign key ke users.id |
expiresAt |
timestamp | Waktu kedaluwarsa |
createdAt |
timestamp | Waktu pembuatan |
teams
Grup untuk mengorganisasi pengguna. Admin dapat menetapkan pengguna ke tim.
| Kolom | Tipe | Deskripsi |
|---|---|---|
id |
uuid | Primary key |
name |
varchar (unik, maks 50 karakter) | Nama tim |
createdAt |
timestamp | Waktu pembuatan |
api_keys
API key untuk akses secara programatik. Kunci mentah ditampilkan sekali saat pembuatan; hanya hash yang disimpan.
| Kolom | Tipe | Catatan |
|---|---|---|
id |
uuid | Primary key |
userId |
uuid | Foreign key ke users.id |
keyHash |
varchar | hash scrypt dari kunci |
name |
varchar | Label yang diberikan pengguna |
createdAt |
timestamp | Waktu pembuatan |
lastUsedAt |
timestamp | Diperbarui pada setiap permintaan terautentikasi |
Kunci diberi awalan si_ diikuti oleh 96 karakter heksadesimal (48 byte acak).
pipelines
Rangkaian tool tersimpan yang dibuat pengguna di UI.
| Kolom | Tipe | Catatan |
|---|---|---|
id |
uuid | Primary key |
name |
varchar | Nama pipeline |
description |
varchar | Deskripsi opsional |
steps |
jsonb | Array objek { toolId, settings } |
createdAt |
timestamp | Waktu pembuatan |
user_files
Pustaka file persisten. Secara default, sebuah editan yang disimpan dimasukkan sebagai baris akar independen ("simpan sebagai baru": version 1, parentId null, sehingga file asli tetap terdaftar), atau sebagai versi yang tertaut ke induk ketika Anda menimpa file asli (parentId diisi, version dinaikkan, menggantikannya). Kolom toolChain mencatat tool yang diterapkan.
| Kolom | Tipe | Deskripsi |
|---|---|---|
id |
uuid | Primary key |
userId |
uuid | FK ke users (CASCADE DELETE) |
originalName |
varchar | Nama file unggahan asli |
storedName |
varchar | Nama file pada disk |
mimeType |
varchar | Tipe MIME |
size |
integer | Ukuran file dalam byte |
width |
integer | Lebar gambar dalam px |
height |
integer | Tinggi gambar dalam px |
version |
integer | Nomor versi (1 = asli) |
parentId |
uuid atau null | FK ke user_files (versi induk) |
toolChain |
jsonb | ID tool yang diterapkan secara berurutan untuk menghasilkan versi ini |
createdAt |
timestamp | Waktu pembuatan |
jobs
Melacak job pemrosesan untuk pelaporan progres dan pembersihan.
| Kolom | Tipe | Catatan |
|---|---|---|
id |
uuid | Primary key |
type |
varchar | Identifikasi tool atau pipeline |
status |
varchar | queued, processing, completed, atau failed |
progress |
real | Fraksi 0.0-1.0 |
inputFiles |
jsonb | Array path file input |
outputPath |
varchar | Path ke file hasil |
settings |
jsonb | Pengaturan tool yang digunakan |
error |
varchar | Pesan kesalahan jika gagal |
createdAt |
timestamp | Waktu pembuatan |
completedAt |
timestamp | Waktu penyelesaian |
settings
Penyimpanan key-value untuk pengaturan seluruh server yang dapat diubah admin dari UI.
| Kolom | Tipe | Catatan |
|---|---|---|
key |
varchar | Primary key |
value |
varchar | Nilai pengaturan |
updatedAt |
timestamp | Waktu pembaruan terakhir |
roles
Peran kustom dengan izin granular.
| Kolom | Tipe | Catatan |
|---|---|---|
id |
uuid | Primary key |
name |
varchar | Nama peran unik |
description |
varchar | Deskripsi opsional |
permissions |
jsonb | Array string izin |
createdAt |
timestamp | Waktu pembuatan |
audit_log
Log aksi yang relevan dengan keamanan.
| Kolom | Tipe | Catatan |
|---|---|---|
id |
uuid | Primary key |
userId |
uuid | FK ke users |
action |
varchar | Tipe aksi |
details |
jsonb | Data khusus aksi |
createdAt |
timestamp | Waktu aksi |
Migrasi
Drizzle menangani migrasi skema. File migrasi berada di apps/api/drizzle/. Selama pengembangan:
cd apps/api
npx drizzle-kit generate # generate a migration from schema changes
npx drizzle-kit migrate # apply pending migrations
Di produksi, migrasi yang tertunda diterapkan secara otomatis saat startup.
Pencadangan dan pemulihan
Database relasional berada di volume SnapOtter-pgdata kontainer Postgres, bukan di volume /data aplikasi.
Opsi 1: pg_dump (direkomendasikan)
# 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
Opsi 2: Snapshot 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 .
Migrasi dari 1.x (SQLite)
Memutakhirkan dari SnapOtter 1.x memiliki panduannya sendiri: lihat Memutakhirkan dari 1.x ke 2.0. Singkatnya, gunakan kembali volume /data Anda yang ada dan 2.0 otomatis mendeteksi serta mengimpor /data/snapotter.db pada boot pertama (atau atur SQLITE_MIGRATE_PATH untuk menunjuk ke sana secara eksplisit). Cadangkan seluruh volume /data terlebih dahulu, bukan hanya snapotter.db: 1.x menggunakan mode SQLite WAL, sehingga kontainer yang dihentikan sering meninggalkan sebagian besar datanya di snapotter.db-wal di samping snapotter.db yang hampir kosong.