Files
SnapOtter/apps/docs/nl/guide/database.md
T
SnapOtterandGitHub d10d0f544f fix: release QA hardening across processing, media, security, and CI gates (#649)
A release-readiness QA pass over the whole product. The commits split into
defects a user would hit and gates that were reporting green while measuring
nothing.

## Fixes that change behaviour

Rate limiting was bypassable on every install: TRUST_PROXY defaulted to true, so
request.ip came from a client-set header and a forged X-Forwarded-For got past
the login limiter. The default is now a private-network trust list.

A transient Postgres outage stranded in-flight jobs, leaving finished output on
disk with no row pointing at it. A reconciler now resolves those rows and adopts
the bytes rather than dropping the work.

A Redis connection that moved to a new address wedged every read-blocked
consumer, so completions stopped signalling while health still answered 200.
Socket timeouts plus subscriber pings recover it.

Installing more than one AI bundle left the shared venv multi-versioned and
silently broke three tools. The installer now reconciles distributions to one
version each.

Converting an image to JXL at quality 1 through 4 returned a 500, because
libjxl 0.7 rejects the distance those values compute. The quality is floored at
what the encoder honours. A missing ffmpeg was also reported to the user as a
corrupt upload; it now says the engine is unavailable.

RAW uploads reached an unpatched LibRaw on arm64, so it is built from source at
0.22.2, and the release scan was split so it can fail on an unfixed critical
instead of hiding it behind ignore-unfixed.

## Gates that could not fail

Two mutation lanes ran zero mutants because Stryker crawled the gitignored docs
build; coverage discarded its whole report on any failing test; the lint gate
skipped root tests, scripts, and two workspaces; and several generated matrices
counted a host missing ffmpeg as a passing tool. Each now measures what it
claims.

Full evidence and the outstanding release items are tracked locally and are not
part of this branch.
2026-07-27 15:37:30 +08:00

8.5 KiB

description, i18n_source_hash, i18n_provenance, i18n_output_hash, i18n_hash_version
description i18n_source_hash i18n_provenance i18n_output_hash i18n_hash_version
PostgreSQL-databaseschema, tabellen, migraties en back-upprocedures voor SnapOtter. a68264552836 machine 0c2305505e16 2

Database

SnapOtter gebruikt PostgreSQL 17 met Drizzle ORM (pg-core / node-postgres) voor gegevensopslag. Het schema is gedefinieerd in apps/api/src/db/schema.ts.

De verbinding wordt geconfigureerd via de omgevingsvariabele DATABASE_URL (standaard postgres://snapotter:snapotter@postgres:5432/snapotter). In Docker Compose slaat de Postgres-container zijn gegevens op in het benoemde volume SnapOtter-pgdata.

Tabellen

users

Slaat gebruikersaccounts op. Wordt bij de eerste run automatisch aangemaakt op basis van DEFAULT_USERNAME en DEFAULT_PASSWORD.

Kolom Type Opmerkingen
id uuid Primaire sleutel
username varchar Uniek, vereist
passwordHash varchar scrypt-hash
role varchar admin, editor of user
mustChangePassword boolean Vlag voor geforceerde wachtwoordreset
createdAt timestamp Aanmaaktijd
updatedAt timestamp Tijd van laatste update

sessions

Actieve aanmeldsessies. Elke rij koppelt een sessietoken aan een gebruiker.

Kolom Type Opmerkingen
id varchar Primaire sleutel (sessietoken)
userId uuid Vreemde sleutel naar users.id
expiresAt timestamp Vervaltijd
createdAt timestamp Aanmaaktijd

teams

Groepen om gebruikers te organiseren. Beheerders kunnen gebruikers aan teams toewijzen.

Kolom Type Beschrijving
id uuid Primaire sleutel
name varchar (uniek, max. 50 tekens) Teamnaam
createdAt timestamp Aanmaaktijd

api_keys

API-sleutels voor programmatische toegang. De onbewerkte sleutel wordt eenmalig getoond bij aanmaken; alleen de hash wordt opgeslagen.

Kolom Type Opmerkingen
id uuid Primaire sleutel
userId uuid Vreemde sleutel naar users.id
keyHash varchar scrypt-hash van de sleutel
name varchar Door de gebruiker opgegeven label
createdAt timestamp Aanmaaktijd
lastUsedAt timestamp Bijgewerkt bij elk geauthenticeerd verzoek

Sleutels beginnen met het voorvoegsel si_ gevolgd door 96 hexadecimale tekens (48 willekeurige bytes).

pipelines

Opgeslagen toolketens die gebruikers in de UI aanmaken.

Kolom Type Opmerkingen
id uuid Primaire sleutel
name varchar Pipelinenaam
description varchar Optionele beschrijving
steps jsonb Array van { toolId, settings }-objecten
createdAt timestamp Aanmaaktijd

user_files

Persistente bestandsbibliotheek. Een opgeslagen bewerking wordt standaard als een onafhankelijke root-rij ingevoegd ("opslaan als nieuw": version 1, parentId null, zodat het origineel in de lijst blijft staan), of als een aan de bovenliggende rij gekoppelde versie wanneer je het origineel overschrijft (parentId ingesteld, version opgehoogd, waarmee het wordt vervangen). De kolom toolChain registreert welke tools zijn toegepast.

Kolom Type Beschrijving
id uuid Primaire sleutel
userId uuid FK naar users (CASCADE DELETE)
originalName varchar Oorspronkelijke bestandsnaam bij upload
storedName varchar Bestandsnaam op schijf
mimeType varchar MIME-type
size integer Bestandsgrootte in bytes
width integer Breedte van de afbeelding in px
height integer Hoogte van de afbeelding in px
version integer Versienummer (1 = origineel)
parentId uuid of null FK naar user_files (bovenliggende versie)
toolChain jsonb Tool-ID's die op volgorde zijn toegepast om deze versie te maken
createdAt timestamp Aanmaaktijd

jobs

Volgt verwerkingsjobs voor voortgangsrapportage en opschoning.

Kolom Type Opmerkingen
id uuid Primaire sleutel
type varchar Tool- of pipeline-identifier
status varchar queued, processing, completed of failed
progress real Fractie van 0.0-1.0
inputFiles jsonb Array van invoerbestandspaden
outputPath varchar Pad naar het resultaatbestand
settings jsonb Gebruikte toolinstellingen
error varchar Foutmelding bij mislukken
createdAt timestamp Aanmaaktijd
completedAt timestamp Voltooiingstijd

settings

Sleutel-waardeopslag voor serverbrede instellingen die beheerders vanuit de UI kunnen wijzigen.

Kolom Type Opmerkingen
key varchar Primaire sleutel
value varchar Instellingswaarde
updatedAt timestamp Tijd van laatste update

roles

Aangepaste rollen met granulaire rechten.

Kolom Type Opmerkingen
id uuid Primaire sleutel
name varchar Unieke rolnaam
description varchar Optionele beschrijving
permissions jsonb Array van rechtenstrings
createdAt timestamp Aanmaaktijd

audit_log

Logboek van beveiligingsrelevante acties.

Kolom Type Opmerkingen
id uuid Primaire sleutel
userId uuid FK naar users
action varchar Actietype
details jsonb Actiespecifieke gegevens
createdAt timestamp Tijd van de actie

user_preferences

UI-status per gebruiker, gesleuteld op voorkeursnaam. Bewaart de vastgezette tools van de startpagina, die via PUT /api/v1/preferences worden geschreven.

Kolom Type Opmerkingen
userId text FK naar users, cascaderend verwijderen. Samen met key de primaire sleutel
key text Naam van de voorkeur. Samen met userId de primaire sleutel
value jsonb Inhoud van de voorkeur
updatedAt timestamp Laatste schrijfactie

Migraties

Drizzle verzorgt schemamigraties. Migratiebestanden staan in apps/api/drizzle/. Tijdens ontwikkeling:

cd apps/api
npx drizzle-kit generate   # generate a migration from schema changes
npx drizzle-kit migrate    # apply pending migrations

In productie worden openstaande migraties automatisch toegepast bij het opstarten.

Back-up en herstel

De relationele database bevindt zich in het SnapOtter-pgdata-volume van de Postgres-container, niet in het /data-volume van de app.

Logische back-up met validatie (aanbevolen)

# Dump into PostgreSQL's portable custom archive format
docker exec SnapOtter-postgres \
  pg_dump --format=custom --no-owner -U snapotter snapotter > snapotter.dump
test -s snapotter.dump
docker exec -i SnapOtter-postgres pg_restore --list < snapotter.dump >/dev/null

# Restore into a fresh/disposable target first and fail on the first SQL error
docker exec -i SnapOtter-postgres \
  pg_restore --exit-on-error --clean --if-exists --no-owner \
  -U snapotter -d snapotter < snapotter.dump

Deze databasedump bevat geen opgeslagen bibliotheekobjecten in /data/files of de duurzame BullMQ-status in Redis. Maak een back-up en herstel deze met de gecoördineerde procedure in Beveiliging en verharding.

Koude volumemomentopname

# Stop every service first, then use your storage platform to snapshot the
# PostgreSQL, app-data, and Redis volumes as one crash-consistent set.
docker compose -f docker/docker-compose.yml stop

Kopieer geen live PostgreSQL-gegevensmap met tar. Stel volumenamen voor voorvoegsels samen per project, dus los de gekoppelde volume-ID's van docker inspect of uw opslagplatform op in plaats van het letterlijke label SnapOtter-pgdata aan te nemen.

Migreren vanaf 1.x (SQLite)

Upgraden vanaf SnapOtter 1.x heeft een eigen gids: zie Upgraden van 1.x naar 2.0. Kort gezegd: hergebruik je bestaande /data-volume, en 2.0 detecteert en importeert /data/snapotter.db automatisch bij de eerste keer opstarten (of stel SQLITE_MIGRATE_PATH in om er expliciet naar te verwijzen). Maak eerst een back-up van het volledige /data-volume, niet alleen van snapotter.db: 1.x gebruikt de SQLite WAL-modus, dus een gestopte container laat vaak het grootste deel van zijn gegevens in snapotter.db-wal staan naast een bijna leeg snapotter.db.