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.
This commit is contained in:
SnapOtter
2026-07-27 15:37:30 +08:00
committed by GitHub
parent bc32f86a07
commit d10d0f544f
855 changed files with 54564 additions and 13092 deletions
+4 -3
View File
@@ -1,8 +1,9 @@
---
description: "Monorepo-structuur, app- en package-architectuur, request-levenscyclus en resourcegebruik van SnapOtter."
i18n_output_hash: 5122b85d1d84
i18n_source_hash: a53946e760b0
i18n_source_hash: 50e076925c4b
i18n_provenance: human
i18n_output_hash: 073fb843bda2
i18n_hash_version: 2
---
# Architectuur {#architecture}
@@ -52,7 +53,7 @@ Gedeelde TypeScript-types, constanten (zoals `APP_VERSION` en tooldefinities) en
### API (`apps/api`) {#api-apps-api}
Een Fastify v5-server die 241 toolroutes over vijf modaliteiten (image, video, audio, PDF, file) blootstelt en het volgende afhandelt:
Een Fastify v5-server die 243 toolroutes over vijf modaliteiten (image, video, audio, PDF, file) blootstelt en het volgende afhandelt:
- Bestandsuploads, beheer van tijdelijke werkruimte en persistente bestandsopslag
- Gebruikersbibliotheek voor bestanden (`user_files`-tabel): een opgeslagen bewerking wordt standaard opgeslagen als een onafhankelijk nieuw bestand, of als een aan de bovenliggende rij gekoppelde versie wanneer je het origineel overschrijft. Ze registreert welke tools zijn toegepast (`toolChain`) en krijgt een automatisch gegenereerde miniatuur voor de Files-pagina
- Tooluitvoering (routeert elk toolverzoek naar de image-engine of AI-brug)
+40 -17
View File
@@ -1,8 +1,9 @@
---
description: "Alle SnapOtter-omgevingsvariabelen met standaardwaarden. Configureer authenticatie, opslag, AI-modellen, analytics en meer."
i18n_source_hash: 8e9e9ca2840c
i18n_source_hash: 25970c776f7c
i18n_provenance: human
i18n_output_hash: 17a9658bf5d8
i18n_output_hash: 05e18ac893a3
i18n_hash_version: 2
---
# Configuratie {#configuration}
@@ -19,28 +20,51 @@ Alle configuratie gebeurt via omgevingsvariabelen. Elke variabele heeft een vers
| `RATE_LIMIT_PER_MIN` | `1000` | Maximaal aantal verzoeken per minuut per IP. Stel in op 0 om rate limiting uit te schakelen. |
| `CORS_ORIGIN` | (leeg) | Door komma's gescheiden toegestane origins voor CORS, of leeg voor alleen dezelfde origin. |
| `LOG_LEVEL` | `info` | Uitgebreidheid van logging. Een van: `fatal`, `error`, `warn`, `info`, `debug`, `trace`. |
| `TRUST_PROXY` | `true` | Vertrouw `X-Forwarded-For`-headers van een reverse proxy. Stel in op `false` als er geen proxy vóór zit. |
| `TRUST_PROXY` | `loopback,linklocal,uniquelocal` | Welke peers het client-IP via `X-Forwarded-For` mogen zetten. De standaardwaarde gelooft alleen een peer uit een privénetwerk, dus een reverse proxy op een Docker-netwerk of in een LAN wordt vertrouwd en de vervalste header van een publieke client niet. Stel alleen `true` in wanneer er een proxy die jij beheert vóór zit op een openbaar adres. |
### Authenticatie {#authentication}
De twee booleans hieronder accepteren alleen `true` en `false`. Al het andere, `1` of `yes` of `on`, komt niet door de validatie en de server stopt voordat hij begint te luisteren.
| Variabele | Standaard | Beschrijving |
|---|---|---|
| `AUTH_ENABLED` | `false` | Stel in op `true` om aanmelden te vereisen. De Docker-image gebruikt standaard `true`. |
| `AUTH_ENABLED` | `true` | Vereist aanmelden. Stel in op `false` om helemaal zonder accounts te draaien, wat elk verzoek adminrechten geeft, dus houd dat op een vertrouwd netwerk. |
| `DEFAULT_USERNAME` | `admin` | Gebruikersnaam voor het initiële adminaccount. Wordt alleen bij de eerste keer opstarten gebruikt. |
| `DEFAULT_PASSWORD` | `admin` | Wachtwoord voor het initiële adminaccount. Wijzig dit na de eerste keer aanmelden. |
| `MAX_USERS` | `0` (onbeperkt) | Maximaal aantal geregistreerde gebruikersaccounts. Stel in op 0 voor onbeperkt. |
| `SESSION_DURATION_HOURS` | `168` | Levensduur van de aanmeldsessie in uren (standaard 7 dagen). |
| `SKIP_MUST_CHANGE_PASSWORD` | - | Stel in op een niet-lege waarde om de verplichte wachtwoordwijzigingsprompt bij de eerste aanmelding over te slaan |
| `SKIP_MUST_CHANGE_PASSWORD` | `false` | Stel in op `true` om de verplichte wachtwoordwijzigingsprompt bij de eerste aanmelding over te slaan. |
### Opslag {#storage}
| Variabele | Standaard | Beschrijving |
|---|---|---|
| `STORAGE_MODE` | `local` | `local` of `s3`. S3/MinIO vereist een licentie met de s3_storage-functie. |
| `DATABASE_URL` | `postgres://snapotter:snapotter@postgres:5432/snapotter` | PostgreSQL-connectiestring. |
| `REDIS_URL` | `redis://redis:6379` | Redis-connectiestring (gebruikt voor BullMQ-taakwachtrijen). |
| `WORKSPACE_PATH` | `./tmp/workspace` | Map voor tijdelijke bestanden tijdens de verwerking. Wordt automatisch opgeschoond. |
| `FILES_STORAGE_PATH` | `./data/files` | Map voor persistente gebruikersbestanden (geüploade afbeeldingen, opgeslagen resultaten). |
| `STORAGE_MODE` | `local` | `local` of `s3`. S3 en MinIO vereisen een licentie met de s3_storage-functie plus de `S3_*`-variabelen hieronder. |
| `DATABASE_URL` | `postgres://snapotter:snapotter@localhost:5432/snapotter` | PostgreSQL-connectiestring. De Compose-stack wijst deze naar zijn `postgres`-service; laat hem leeg (samen met `REDIS_URL`) om de ingebedde modus te krijgen. |
| `REDIS_URL` | `redis://localhost:6379` | Redis-connectiestring (gebruikt voor BullMQ-taakwachtrijen). Compose wijst deze naar zijn `redis`-service. |
| `WORKSPACE_PATH` | `./tmp/workspace` | Map voor tijdelijke bestanden tijdens de verwerking. Wordt automatisch opgeschoond. De image stelt `/tmp/workspace` in. |
| `FILES_STORAGE_PATH` | `./data/files` | Map voor persistente gebruikersbestanden (geüploade afbeeldingen, opgeslagen resultaten). De image stelt `/data/files` in. |
### S3-objectopslag {#s3-object-storage}
Wordt alleen gelezen wanneer `STORAGE_MODE=s3`. Ontbreekt een van de drie verplichte variabelen, dan mislukt het opstarten met de naam van de variabele die je hebt weggelaten.
| Variabele | Standaard | Beschrijving |
|---|---|---|
| `S3_BUCKET` | (leeg) | Bucket die uploads en uitvoer bevat. Verplicht. |
| `S3_ACCESS_KEY_ID` | (leeg) | Access key. Verplicht. In de container kun je hem in plaats daarvan koppelen, via `S3_ACCESS_KEY_ID_FILE`. |
| `S3_SECRET_ACCESS_KEY` | (leeg) | Secret key. Verplicht. Dezelfde bestandsconventie: `S3_SECRET_ACCESS_KEY_FILE`. |
| `S3_REGION` | `us-east-1` | Regio van de bucket. |
| `S3_ENDPOINT` | (leeg) | Aangepast endpoint voor MinIO, R2, Backblaze en andere S3-compatibele opslag. Leeg betekent AWS. |
| `S3_FORCE_PATH_STYLE` | `false` | Stel in op `true` voor MinIO en al het andere dat `endpoint/bucket/key` wil in plaats van virtual-hostadressering. |
| `S3_PREFIX` | (leeg) | Sleutelprefix, zodat één bucket meerdere instanties kan bevatten. |
### Versleuteling in rust {#encryption-at-rest}
| Variabele | Standaard | Beschrijving |
|---|---|---|
| `DATA_ENCRYPTION_KEY` | (leeg) | 64 hexadecimale tekens (32 bytes). Versleutelt gevoelige instellingen die in de database zijn opgeslagen. Alles wat geen 64 hexadecimale tekens is, wordt bij het opstarten geweigerd. |
| `DATA_ENCRYPTION_KEY_PREVIOUS` | (leeg) | De sleutel waar je vanaf roteert, met dezelfde indeling. Stel beide in tijdens een rotatie zodat bestaande rijen nog steeds ontsleuteld worden, en verwijder deze daarna. |
### Ingebedde modus {#embedded-mode}
@@ -59,16 +83,15 @@ Opmerking over telemetrie: de ingebedde modus erft de analytics-standaard van de
| Variabele | Standaard | Beschrijving |
|---|---|---|
| `MAX_UPLOAD_SIZE_MB` | `100` | Maximale bestandsgrootte per upload in megabytes. Stel in op 0 voor onbeperkt. |
| `MAX_BATCH_SIZE` | `100` | Maximaal aantal bestanden in één batchverzoek. Stel in op 0 voor onbeperkt. |
| `MAX_UPLOAD_SIZE_MB` | `0` (onbeperkt) | Maximale bestandsgrootte per upload in megabytes. Stel in op 0 voor onbeperkt. De gepubliceerde image wordt geleverd met `0`; een build vanaf de broncode begint op 100. |
| `MAX_BATCH_SIZE` | `0` (onbeperkt) | Maximaal aantal bestanden in één batchverzoek. Stel in op 0 voor onbeperkt. De gepubliceerde image wordt geleverd met `0`; een build vanaf de broncode begint op 100. |
| `CONCURRENT_JOBS` | `0` (auto) | Aantal batchtaken dat parallel draait. Stel in op 0 om automatisch te detecteren op basis van beschikbare CPU-cores. |
| `MAX_MEGAPIXELS` | `0` (onbeperkt) | Maximaal toegestane beeldresolutie in megapixels. Stel in op 0 voor onbeperkt. |
| `MAX_WORKER_THREADS` | `0` (auto) | Maximaal aantal worker-threads voor beeldverwerking. Stel in op 0 om automatisch te detecteren op basis van beschikbare CPU-cores. |
| `PROCESSING_TIMEOUT_S` | `0` (geen limiet) | Maximale verwerkingstijd per verzoek in seconden. Stel in op 0 voor geen timeout. |
| `MAX_PIPELINE_STEPS` | `20` | Maximaal aantal stappen in een pijplijn. Stel in op 0 voor geen limiet. |
| `MAX_CANVAS_PIXELS` | `0` (geen limiet) | Maximale canvasgrootte in pixels voor uitvoerafbeeldingen. Stel in op 0 voor geen limiet. |
| `MAX_SVG_SIZE_MB` | `0` (onbeperkt) | Maximale SVG-bestandsgrootte in megabytes. Stel in op 0 voor onbeperkt. |
| `MAX_SPLIT_GRID` | `100` | Maximale rasterdimensie voor de tool om afbeeldingen te splitsen. |
| `MAX_SVG_SIZE_MB` | `50` | Grootste SVG die vóór het opschonen wordt geaccepteerd, in megabytes. `0` gedraagt zich hier anders dan in de rijen eromheen. Het verwijdert de groottelimiet vóór het parsen volledig in plaats van hem te verhogen, dus laat deze ingesteld staan. |
| `MAX_PDF_PAGES` | `0` (onbeperkt) | Maximaal aantal PDF-pagina's voor PDF-naar-image-conversie. Stel in op 0 voor onbeperkt. |
### Opschoning {#cleanup}
@@ -82,7 +105,7 @@ Opmerking over telemetrie: de ingebedde modus erft de analytics-standaard van de
| Variabele | Standaard | Beschrijving |
|---|---|---|
| `DEFAULT_THEME` | `light` | Standaardthema voor nieuwe sessies. `light` of `dark`. |
| `DEFAULT_THEME` | `light` | Standaardthema voor nieuwe sessies. `light`, `dark` of `system`. |
| `DEFAULT_LOCALE` | `en` | Standaardtaal van de interface. |
| `DEFAULT_TOOL_VIEW` | `sidebar` | Standaard toollay-out. `sidebar` of `fullscreen`. |
@@ -124,13 +147,13 @@ services:
image: postgres:17-alpine
environment:
POSTGRES_USER: snapotter
POSTGRES_PASSWORD: snapotter
POSTGRES_PASSWORD: snapotter # Wijzig dit voor niet-lokale implementaties
POSTGRES_DB: snapotter
volumes:
- SnapOtter-pgdata:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U snapotter"]
test: ["CMD-SHELL", "pg_isready -U snapotter -d snapotter"]
interval: 10s
timeout: 5s
retries: 12
+5 -4
View File
@@ -1,8 +1,9 @@
---
description: "Hoe je kunt bijdragen aan SnapOtter. Bugmeldingen, functieverzoeken, pull requests en CLA-vereisten."
i18n_source_hash: 528802503035
i18n_source_hash: 6c920a5f83e0
i18n_provenance: human
i18n_output_hash: fb98487dded5
i18n_output_hash: 90ecc9252cbc
i18n_hash_version: 2
---
# Bijdragen {#contributing}
@@ -53,7 +54,7 @@ Als je bijdraagt namens je werkgever en je werkgever de IP-rechten op je werk be
### Vereisten {#prerequisites}
- Node.js 22+
- Node.js 22.22+
- pnpm 9+
- Python 3.11+ (alleen voor AI-tools)
- Docker (optioneel, voor volledige integratietests)
@@ -71,7 +72,7 @@ docker compose -f docker-compose.dev.yml up -d
# Install dependencies
pnpm install
# Start dev servers (web on :1349, API on :13490)
# Start dev servers (web on :1351, API on :13490)
pnpm dev
```
+33 -13
View File
@@ -1,8 +1,9 @@
---
description: "PostgreSQL-databaseschema, tabellen, migraties en back-upprocedures voor SnapOtter."
i18n_source_hash: 50d5d4f220cf
i18n_provenance: human
i18n_output_hash: e283a792e124
i18n_source_hash: a68264552836
i18n_provenance: machine
i18n_output_hash: 0c2305505e16
i18n_hash_version: 2
---
# Database {#database}
@@ -145,6 +146,17 @@ Logboek van beveiligingsrelevante acties.
| `details` | jsonb | Actiespecifieke gegevens |
| `createdAt` | timestamp | Tijd van de actie |
### user_preferences {#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 {#migrations}
Drizzle verzorgt schemamigraties. Migratiebestanden staan in `apps/api/drizzle/`. Tijdens ontwikkeling:
@@ -161,25 +173,33 @@ In productie worden openstaande migraties automatisch toegepast bij het opstarte
De relationele database bevindt zich in het `SnapOtter-pgdata`-volume van de Postgres-container, niet in het `/data`-volume van de app.
**Optie 1: pg_dump (aanbevolen)**
**Logische back-up met validatie (aanbevolen)**
```bash
# Dump the database while the stack is running
docker exec SnapOtter-postgres pg_dump -U snapotter snapotter > backup.sql
# 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 database
cat backup.sql | docker exec -i SnapOtter-postgres psql -U snapotter snapotter
# 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
```
**Optie 2: Volume-snapshot**
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](/nl/guide/security#backup-and-recovery).
**Koude volumemomentopname**
```bash
# 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 .
# 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) {#migrating-from-1-x-sqlite}
Upgraden vanaf SnapOtter 1.x heeft een eigen gids: zie [Upgraden van 1.x naar 2.0](./upgrading). 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`.
+24 -13
View File
@@ -1,8 +1,9 @@
---
description: "Implementeer SnapOtter in productie met Docker. Hardwarevereisten, GPU-installatie en reverse-proxyconfiguraties voor Nginx, Traefik en Cloudflare."
i18n_output_hash: 21ff542fcb0c
i18n_source_hash: 98172965118b
i18n_source_hash: 2a722f86da75
i18n_provenance: human
i18n_output_hash: 65686fc8753a
i18n_hash_version: 2
---
# Implementatie {#deployment}
@@ -47,7 +48,7 @@ services:
# - MAX_USERS=0 # Max user accounts
# --- Networking ---
# - TRUST_PROXY=true # Trust X-Forwarded-For headers (set false if not behind a proxy)
# - TRUST_PROXY=loopback,linklocal,uniquelocal # Which peers may set the client IP via X-Forwarded-For (default shown)
# --- Bind mount permissions ---
# - PUID=1000 # Match your host user's UID (run: id -u)
@@ -82,7 +83,7 @@ services:
- SnapOtter-pgdata:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U snapotter"]
test: ["CMD-SHELL", "pg_isready -U snapotter -d snapotter"]
interval: 10s
timeout: 5s
retries: 12
@@ -170,13 +171,13 @@ services:
container_name: SnapOtter-postgres
environment:
POSTGRES_USER: snapotter
POSTGRES_PASSWORD: snapotter
POSTGRES_PASSWORD: snapotter # Wijzig dit voor niet-lokale implementaties
POSTGRES_DB: snapotter
volumes:
- SnapOtter-pgdata:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U snapotter"]
test: ["CMD-SHELL", "pg_isready -U snapotter -d snapotter"]
interval: 10s
timeout: 5s
retries: 12
@@ -207,13 +208,17 @@ volumes:
docker compose -f docker-compose-gpu.yml up -d
```
Controleer de CUDA-detectie in de logs:
### Controleer GPU-versnelling {#verify-gpu-acceleration}
Controleer CUDA-detectie in de logboeken:
```bash
docker logs SnapOtter 2>&1 | head -20
# Look for: [gpu] CUDA available via torch
```
Als AI-tools op de CPU draaien, ook al zijn `--gpus all` en de NVIDIA Container Toolkit correct ingesteld, installeer dan de betreffende bundel opnieuw (bijvoorbeeld Achtergrondverwijdering) via **Instellingen → AI-functies**. Het installatieprogramma herstelt de GPU-build van ONNX Runtime, die een build met alleen CPU die door een andere bundel (zoals transcriptie) wordt binnengehaald, anders in de gedeelde AI-omgeving kan overschaduwen. Als het opnieuw installeren via de gebruikersinterface de GPU op een oudere image niet herstelt, raadpleeg dan de handmatige reparatie in [probleem #490](https://github.com/snapotter-hq/SnapOtter/issues/490).
## Hardwarevereisten {#hardware-requirements}
Deze cijfers komen uit benchmarks op een reeks systemen, van een moderne amd64-werkstation met een NVIDIA RTX 4070 tot een Raspberry Pi, waarbij op elk systeem de volledige toolcatalogus werd uitgevoerd en de Docker-resourcelimieten werden doorlopen om de echte ondergrens te vinden.
@@ -436,11 +441,11 @@ De opstartfout noemt de exacte UID die je moet gebruiken, dus de snelste weg is
| `AUTH_ENABLED` | `true` | Inlogvereiste in-/uitschakelen |
| `DEFAULT_USERNAME` | `admin` | Initiële beheerdersgebruikersnaam |
| `DEFAULT_PASSWORD` | `admin` | Initieel beheerderswachtwoord (wijziging verplicht bij eerste login) |
| `MAX_UPLOAD_SIZE_MB` | `100` | Uploadlimiet per bestand |
| `MAX_BATCH_SIZE` | `100` | Max. bestanden per batchverzoek |
| `MAX_UPLOAD_SIZE_MB` | `0` (onbeperkt) | Uploadlimiet per bestand in MB. De image wordt met `0` geleverd; een build vanaf de broncode begint bij 100 |
| `MAX_BATCH_SIZE` | `0` (onbeperkt) | Max. bestanden per batchverzoek. De image wordt met `0` geleverd; een build vanaf de broncode begint bij 100 |
| `RATE_LIMIT_PER_MIN` | `1000` | API-verzoeken per minuut per IP (stel 0 in om uit te schakelen) |
| `MAX_USERS` | `0` (onbeperkt) | Maximaal aantal gebruikersaccounts |
| `TRUST_PROXY` | `true` | Vertrouw X-Forwarded-For-headers van reverse proxy |
| `TRUST_PROXY` | `loopback,linklocal,uniquelocal` | Welke peers het client-IP via `X-Forwarded-For` mogen zetten. Standaard alleen privénetwerken |
| `PUID` | `999` | Draaien onder deze UID (voor bind-mount-permissies) |
| `PGID` | `999` | Draaien onder deze GID (voor bind-mount-permissies) |
| `LOG_LEVEL` | `info` | Logbreedsprakigheid: fatal, error, warn, info, debug, trace |
@@ -483,7 +488,13 @@ curl http://localhost:1349/api/v1/health
## Reverse proxy {#reverse-proxy}
SnapOtter stelt `TRUST_PROXY=true` standaard in zodat ratelimiting en logging het echte client-IP uit de `X-Forwarded-For`-headers gebruiken.
`TRUST_PROXY` staat standaard op `loopback,linklocal,uniquelocal`, dus SnapOtter gelooft `X-Forwarded-For` alleen van een peer in een privénetwerk. Een reverse proxy op dezelfde host, op een Docker-netwerk of in je LAN wordt meteen vertrouwd, waardoor ratelimiting, de brute-force-begrenzer bij het inloggen, het auditlogboek en de enterprise-IP-allowlist allemaal zonder configuratie het echte client-IP zien.
Stel `TRUST_PROXY=true` alleen in wanneer de proxy ervoor SnapOtter bereikt vanaf een **openbaar** adres, bijvoorbeeld een cloudloadbalancer op een ander netwerk. Op een rechtstreeks blootgestelde instantie maakt die waarde `request.ip` stuurbaar voor een aanvaller, want wie de header steeds wisselt, krijgt per verzoek een verse ratelimit-teller.
Twee dingen om te weten voordat je client-IP's gaat meten. Docker Desktop op macOS en Windows bedient een gepubliceerde poort via een userland-proxy die elk bronadres herschrijft naar de VM-gateway `192.168.65.1`; daar haalt geen enkele waarde van `TRUST_PROXY` de echte client terug, dus draai alles wat aan het internet hangt op Linux. En op elk platform wordt een gepubliceerde poort benaderen via `localhost` gezien als de bridge-gateway in plaats van als jouw client, zodat een test op localhost je niets vertelt over hoe een echte client wordt toegekend. De volledige tabel met `TRUST_PROXY`-waarden en het voorbehoud rond Docker Desktop staan in [SECURITY.md](https://github.com/snapotter-hq/SnapOtter/blob/main/SECURITY.md#client-ip-resolution-trust_proxy).
Voor elke onderstaande proxy zijn twee dingen van belang: sta grote verzoekinstanties (uploads) toe en buffer geen antwoorden. Een proxy die antwoorden buffert, onderbreekt de SSE-voortgang en, beter zichtbaar, zorgt ervoor dat het downloaden van grote bestanden "start maar nooit eindigt", omdat de proxy het hele bestand vasthoudt voordat het wordt doorgegeven. SnapOtter verzendt `X-Accel-Buffering: no` bij downloads, zodat nginx deze streamt, zelfs als de buffering elders is ingeschakeld, maar voor andere proxy's dan nginx moet de responsbuffering expliciet zijn uitgeschakeld (weergegeven in elke configuratie hieronder). Als een download halverwege vastloopt, is een bufferproxy ervoor het eerste wat u moet controleren.
### Nginx {#nginx}
@@ -505,7 +516,7 @@ server {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# SSE support (batch progress, feature install progress)
# Reacties streamen in plaats van bufferen: nodig voor SSE-voortgang (batch, AI, installatie van functies) en voor het downloaden van grote bestanden.
proxy_buffering off;
proxy_read_timeout 300s;
}
@@ -549,7 +560,7 @@ images.example.com {
}
```
`flush_interval -1` schakelt responsbuffering uit, wat vereist is voor SSE-voortgangsgebeurtenissen (batchverwerking, AI-tools, feature-installaties). De verlengde time-outs laten grote bestandsuploads voltooien zonder dat Caddy de verbinding vroegtijdig sluit.
`flush_interval -1` schakelt responsbuffering uit, wat nodig is voor SSE-voortgangsgebeurtenissen (batchverwerking, AI-tools, functie-installaties) en voor het downloaden van grote bestanden om door te streamen in plaats van te vertragen. Dankzij de verlengde time-outs kunnen grote bestandsuploads worden voltooid zonder dat Caddy de verbinding vroegtijdig verbreekt.
### Cloudflare Tunnels {#cloudflare-tunnels}
+19 -7
View File
@@ -1,8 +1,9 @@
---
description: "Lokale ontwikkelomgeving opzetten, commando's, codeconventies en hoe je een nieuwe tool aan SnapOtter toevoegt."
i18n_source_hash: cb03724d2829
i18n_provenance: human
i18n_output_hash: 057d7364f4cc
i18n_source_hash: 56acc1bf9a9b
i18n_provenance: machine
i18n_output_hash: f8e939b4ce8e
i18n_hash_version: 2
---
# Ontwikkelaarsgids {#developer-guide}
@@ -11,12 +12,12 @@ Hoe je een lokale ontwikkelomgeving opzet en code bijdraagt aan SnapOtter.
## Vereisten {#prerequisites}
- [Node.js](https://nodejs.org/) 22+
- [Node.js](https://nodejs.org/) 22.22+
- [pnpm](https://pnpm.io/) 9+ (`corepack enable && corepack prepare pnpm@latest --activate`)
- [Docker](https://www.docker.com/) (vereist voor lokale Postgres + Redis, containerbuilds en AI-functies)
- Git
Python 3.10+ is alleen nodig als je aan de AI/ML-sidecar werkt (achtergrond verwijderen, opschalen, OCR).
Python 3.11+ is alleen nodig als je aan de AI/ML-sidecar werkt (achtergrond verwijderen, opschalen, OCR).
## Installatie {#setup}
@@ -32,10 +33,10 @@ Dit start twee dev-servers:
| Service | URL | Opmerkingen |
|----------|--------------------------|------------------------------------|
| Frontend | http://localhost:1349 | Vite-dev-server, proxyt /api |
| Frontend | http://localhost:1351 | Vite-dev-server, proxyt /api |
| Backend | http://localhost:13490 | Fastify-API (bereikbaar via proxy) |
Open http://localhost:1349 in je browser. Meld je aan met `admin` / `admin`. Je wordt gevraagd het wachtwoord te wijzigen bij de eerste aanmelding.
Open http://localhost:1351 in je browser. Meld je aan met `admin` / `admin`. Je wordt gevraagd het wachtwoord te wijzigen bij de eerste aanmelding.
## Projectstructuur {#project-structure}
@@ -220,6 +221,17 @@ Gebruik BuildKit-cachemounts voor snellere rebuilds:
DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile -t snapotter:latest .
```
## Versiedomeinen vrijgeven {#release-version-domains}
SnapOtter heeft opzettelijk drie versiedomeinen. Kopieer tijdens een release niet het ene domein naar het andere:
- De releaseversie van de applicatie omvat het rootmanifest, alle privéwerkruimtepakketten en `APP_VERSION`. Semantic-release levert deze waarde, en `pnpm version:sync <version>` werkt elke werkruimte bij voordat een applicatie wordt uitgebracht.
- OpenAPI `info.version` is het stabiele publieke API-groot contract. Alle gelokaliseerde specificaties blijven op `<major>.0.0` voor compatibele applicatiereleases en veranderen alleen wanneer het API-contract overgaat naar een nieuwe hoofdversie.
- `docker/feature-manifest.json` behoudt `imageVersion: 2.0.0` als het onveranderlijke historische opslagtijdperk met featurebundels. Deze v2-archiefpaden zijn geen applicatiepakketversies. Nauwkeurige OCR maakt gebruik van runtime-indeling v3 en registreert de herkomst van de applicatierelease afzonderlijk.
`tests/unit/infra/release-version-policy.test.ts` handhaaft deze grenzen. Een nieuw versiedomein of een nieuwe migratie moet dat contract en het relevante artefactmigratieontwerp samen bijwerken.
De onafhankelijke API- en legacy-bundelwaarden bevinden zich in `config/release-version-policy.json`; Synchronisatie van de applicatieversie mag dat beleidsbestand nooit impliciet herschrijven.
## Omgevingsvariabelen {#environment-variables}
Zie de [Configuratiegids](/nl/guide/configuration) voor de volledige lijst. De belangrijkste voor ontwikkeling:
+8 -7
View File
@@ -1,8 +1,9 @@
---
description: "SnapOtter Docker-image-tags, GPU-benchmarks, versievastzetting en multiplatformondersteuning voor AMD64 en ARM64."
i18n_output_hash: ae5482dbdd3c
i18n_source_hash: fda322e78b4b
i18n_source_hash: 566e20ca07fc
i18n_provenance: human
i18n_output_hash: 7d7635cbf7a2
i18n_hash_version: 2
---
# Docker-image {#docker-image}
@@ -93,13 +94,13 @@ services:
image: postgres:17-alpine
environment:
POSTGRES_USER: snapotter
POSTGRES_PASSWORD: snapotter
POSTGRES_PASSWORD: snapotter # Wijzig dit voor niet-lokale implementaties
POSTGRES_DB: snapotter
volumes:
- SnapOtter-pgdata:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U snapotter"]
test: ["CMD-SHELL", "pg_isready -U snapotter -d snapotter"]
interval: 10s
timeout: 5s
retries: 12
@@ -140,9 +141,9 @@ Voeg voor NVIDIA CUDA-versnelling via Docker Compose de deploy-sectie toe aan de
| Tag | Beschrijving |
|-----|------------|
| `latest` | Nieuwste release |
| `1.11.0` | Exacte versie |
| `1.11` | Nieuwste patch in 1.11.x |
| `1` | Nieuwste minor in 1.x |
| `2.1.0` | Exacte versie |
| `2.1` | Nieuwste patch in 2.1.x |
| `2` | Nieuwste minor in 2.x |
## Platforms {#platforms}
+28 -61
View File
@@ -1,8 +1,9 @@
---
description: "Installeer SnapOtter met Docker in één commando. Inclusief Docker Compose-installatie, bouwen vanaf broncode en een volledig functieoverzicht."
i18n_output_hash: d29d27e8097b
i18n_source_hash: 68bf7f60b68d
i18n_provenance: human
i18n_source_hash: 8040133a6982
i18n_provenance: machine
i18n_output_hash: 034d42379189
i18n_hash_version: 2
---
# Aan de slag {#getting-started}
@@ -17,7 +18,7 @@ Verken de volledige UI op [demo.snapotter.com](https://demo.snapotter.com) - gee
docker run -d --name SnapOtter -p 1349:1349 -v SnapOtter-data:/data snapotter/snapotter:latest
```
Deze enkele container draait alles wat hij nodig heeft: zonder ingestelde `DATABASE_URL` start hij zijn eigen PostgreSQL en Redis op de loopback-interface (embedded-modus) en houdt alle data in het `SnapOtter-data`-volume. Het is de snelste manier om SnapOtter te proberen of zelf te hosten op een homelab. Draai voor productie de [Docker Compose](#docker-compose)-stack hieronder, die PostgreSQL en Redis in hun eigen containers houdt. De embedded-modus draait als root (de standaard) en schakelt zichzelf automatisch uit zodra je `DATABASE_URL` instelt.
Deze enkele container voert alles uit wat hij nodig heeft: zonder `DATABASE_URL` ingesteld, start hij zijn eigen PostgreSQL en Redis op de loopback-interface (embedded mode) en bewaart hij alle gegevens in het `SnapOtter-data`-volume. Het is de snelste manier om SnapOtter uit te proberen of zelf te hosten op een thuislab. Gebruik voor productie de [canonieke Docker Compose-stack](#docker-compose), die PostgreSQL en Redis in hun eigen containers bewaart. De ingebouwde modus wordt uitgevoerd als root (standaard) en wordt automatisch uitgeschakeld zodra u `DATABASE_URL` instelt.
Installeer je op een Raspberry Pi, een oude laptop of een kleine VPS? Zie [Setups met beperkte resources](/nl/guide/low-resource) voor een afgestemd stappenplan en wat je van beperkte hardware kunt verwachten.
@@ -40,7 +41,7 @@ Voeg `--gpus all` toe voor NVIDIA CUDA-versnelde achtergrondverwijdering, opscha
docker run -d --name SnapOtter -p 1349:1349 --gpus all -v SnapOtter-data:/data snapotter/snapotter:latest
```
Vereist de [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html). Valt automatisch terug op CPU wanneer CUDA niet beschikbaar is. Intel/AMD iGPU-versnelling via VA-API, Quick Sync of OpenCL wordt vandaag niet ondersteund voor AI-inferentie. Zie [Docker Tags](/nl/guide/docker-tags) voor benchmarks.
Vereist de [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html). Valt automatisch terug naar de CPU wanneer CUDA niet beschikbaar is. Intel/AMD iGPU-versnelling via VA-API, Quick Sync of OpenCL wordt momenteel niet ondersteund voor AI-inferentie. Zie [Docker-tags](/nl/guide/docker-tags) voor benchmarks. Als AI-tools ondanks `--gpus all` op de CPU draaien, zie dan [GPU-versnelling verifiëren](/nl/guide/deployment#verify-gpu-acceleration).
:::
::: details Ook op GHCR
@@ -51,67 +52,33 @@ docker run -d --name SnapOtter -p 1349:1349 -v SnapOtter-data:/data ghcr.io/snap
Beide registries publiceren bij elke release dezelfde image.
:::
## Docker Compose {#docker-compose}
## Docker Componeer {#docker-compose}
```yaml
services:
SnapOtter:
image: snapotter/snapotter:latest # or ghcr.io/snapotter-hq/snapotter:latest
ports:
- "1349:1349"
volumes:
- SnapOtter-data:/data
environment:
- AUTH_ENABLED=true
- DEFAULT_USERNAME=admin
- DEFAULT_PASSWORD=admin
- DATABASE_URL=postgres://snapotter:snapotter@postgres:5432/snapotter
- REDIS_URL=redis://redis:6379
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stopped
Gebruik het productiebestand dat bij elke release wordt onderhouden en getest in plaats van een verkort Compose-voorbeeld van deze pagina te kopiëren:
postgres:
image: postgres:17-alpine
environment:
POSTGRES_USER: snapotter
POSTGRES_PASSWORD: snapotter
POSTGRES_DB: snapotter
volumes:
- SnapOtter-pgdata:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U snapotter"]
interval: 10s
timeout: 5s
retries: 12
```bash
install -d -m 700 snapotter && cd snapotter
curl --proto '=https' --tlsv1.2 -fsSLo docker-compose.yml \
https://raw.githubusercontent.com/snapotter-hq/SnapOtter/v2.1.0/docker/docker-compose.yml
redis:
image: redis:8-alpine
command: ["redis-server", "--maxmemory-policy", "noeviction", "--appendonly", "yes"]
volumes:
- SnapOtter-redisdata:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 12
# Keep generated service credentials out of shell history and world-readable files.
umask 077
POSTGRES_PASSWORD="$(openssl rand -hex 32)"
REDIS_PASSWORD="$(openssl rand -hex 32)"
printf 'POSTGRES_PASSWORD=%s\nREDIS_PASSWORD=%s\n' \
"$POSTGRES_PASSWORD" "$REDIS_PASSWORD" > .env
volumes:
SnapOtter-data:
SnapOtter-pgdata:
SnapOtter-redisdata:
docker compose -f docker-compose.yml pull
docker compose -f docker-compose.yml up -d --no-build
```
Zie [Configuratie](/nl/guide/configuration) voor alle omgevingsvariabelen.
De canonieke [`docker/docker-compose.yml`](https://github.com/snapotter-hq/SnapOtter/blob/v2.1.0/docker/docker-compose.yml) omvat alle vier de runtimevolumes, gezondheidscontroles, resourcelimieten, duurzame Redis-configuratie, vastgezette database-/cache-images en de huidige containerverharding. Wijzig het standaard beheerderswachtwoord onmiddellijk na de eerste keer inloggen. Voor een reproduceerbare implementatie maakt u de SnapOtter-toepassingsimage vast aan de releasetag of -digest die u hebt geverifieerd, in plaats van `latest` te volgen.
Zie [Configuratie](/nl/guide/configuration) voor alle omgevingsvariabelen en [Beveiliging en beveiliging](/nl/guide/security) voor geheimen, netwerkbeleid en back-uprichtlijnen.
## Bouwen vanaf broncode {#build-from-source}
**Vereisten:** Node.js 22+, pnpm 9+, Docker (voor Postgres + Redis), Python 3.10+ (voor AI-functies), Git.
**Vereisten:** Node.js 22.22+, pnpm 9+, Docker (voor Postgres + Redis), Python 3.11+ (voor AI-functies), Git.
```bash
git clone https://github.com/snapotter-hq/SnapOtter.git
@@ -121,7 +88,7 @@ pnpm install
pnpm dev
```
- Frontend: [http://localhost:1349](http://localhost:1349)
- Frontend: [http://localhost:1351](http://localhost:1351)
- Backend: [http://localhost:13490](http://localhost:13490)
## Wat je kunt doen {#what-you-can-do}
@@ -130,11 +97,11 @@ pnpm dev
| Modaliteit | Aantal | Voorbeeldtools |
|----------|-------|---------------|
| **Afbeelding** | 105 | Formaat wijzigen, Bijsnijden, Comprimeren, Converteren, Achtergrond verwijderen, Upscale, OCR, Watermerk, Collage, Inkleuren, GIF-tools, formaatpresets |
| **Afbeelding** | 107 | Formaat wijzigen, Bijsnijden, Comprimeren, Converteren, Achtergrond verwijderen, Upscale, OCR, Watermerk, Collage, Inkleuren, GIF-tools, formaatpresets |
| **Video** | 57 | Trimmen, Bijsnijden, Comprimeren, Converteren, Samenvoegen, Audio extraheren, Automatische ondertitels, Video naar GIF, Formaat wijzigen, Stabiliseren, formaatpresets |
| **Audio** | 27 | Trimmen, Samenvoegen, Converteren, Normaliseren, Ruisonderdrukking, Transcriberen, Pitch verschuiven, Fade, Beltoonmaker, formaatpresets |
| **PDF / Document** | 42 | Samenvoegen, Splitsen, Comprimeren, OCR, Watermerk, Redigeren, Word naar PDF, Excel naar PDF, Roteren, Beveiligen, Repareren |
| **Bestanden** | 10 | CSV naar JSON, JSON naar XML, CSV's samenvoegen, CSV splitsen, ZIP maken, ZIP uitpakken, Grafiekmaker, YAML/JSON |
| **PDF / Document** | 29 | Samenvoegen, Splitsen, Comprimeren, OCR, Watermerk, Redigeren, Word naar PDF, Excel naar PDF, Roteren, Beveiligen, Repareren |
| **Bestanden** | 23 | CSV naar JSON, JSON naar XML, CSV's samenvoegen, CSV splitsen, ZIP maken, ZIP uitpakken, Grafiekmaker, YAML/JSON |
### Pijplijnen {#pipelines}
+4 -3
View File
@@ -1,7 +1,8 @@
---
i18n_source_hash: f5de74aee1b9
i18n_source_hash: 521c03a6416c
i18n_provenance: machine
i18n_output_hash: ac770c68d171
i18n_output_hash: 56ad22d26411
i18n_hash_version: 2
---
# Setups met beperkte resources {#low-resource-setups}
@@ -59,7 +60,7 @@ services:
image: postgres:17-alpine
environment:
- POSTGRES_USER=snapotter
- POSTGRES_PASSWORD=snapotter
- POSTGRES_PASSWORD=snapotter # Wijzig dit voor niet-lokale implementaties
- POSTGRES_DB=snapotter
volumes:
- ./postgres-data:/var/lib/postgresql/data
+12 -7
View File
@@ -1,8 +1,9 @@
---
description: "Stel SCIM 2.0-provisioning in om gebruikers en groepen vanuit je identity provider naar SnapOtter te synchroniseren. Behandelt Okta, Azure AD / Entra ID en aangepaste integraties."
i18n_source_hash: bbd50119ec12
i18n_source_hash: 06ee702b386e
i18n_provenance: human
i18n_output_hash: 9c1e925bdb7c
i18n_output_hash: e058234e6981
i18n_hash_version: 2
---
# SCIM-provisioning {#scim-provisioning}
@@ -17,7 +18,7 @@ SCIM-provisioning vereist een **enterprise**-licentie met de `scim`-functie. Het
- Een draaiende SnapOtter-instance die bereikbaar is via een publieke URL
- Een enterprise-licentiesleutel met de `scim`-functie
- Beheerderstoegang tot SnapOtter (de `users:manage`-permissie is vereist om een SCIM-token te genereren of in te trekken)
- Een ingebouwd SnapOtter `admin`-account met de volledige effectieve machtigingenset. Een gedelegeerde aangepaste rol of een beheerder-API-sleutel waarvoor geen beheerdersmachtiging bestaat, kan het globale SCIM-token niet genereren of intrekken.
- Beheerderstoegang tot de provisioning-instellingen van je identity provider
## Snelstart {#quick-start}
@@ -34,7 +35,7 @@ Het antwoord bevat het token. Sla het meteen op; het kan niet opnieuw worden opg
```json
{
"token": "a1b2c3d4e5f6...",
"token": "so_scim_v2_a1b2c3d4e5f6...",
"message": "Save this token - it cannot be retrieved again"
}
```
@@ -49,15 +50,19 @@ SCIM-eindpunten gebruiken een specifiek Bearer-token, los van gebruikerssessies
### Een token genereren {#generating-a-token}
`POST /api/v1/enterprise/scim/token` genereert een nieuw SCIM-token. Dit eindpunt vereist een geldige sessie met de `users:manage`-permissie.
`POST /api/v1/enterprise/scim/token` genereert een nieuw SCIM-token. Omdat het token gebruikers in het hele exemplaar kan inrichten en muteren, vereist dit eindpunt de ingebouwde `admin`-rol met de volledige effectieve beheerdersmachtigingenset. Het vasthouden van `users:manage` in een aangepaste rol is niet voldoende.
Het token wordt precies één keer in platte tekst teruggegeven. SnapOtter slaat alleen een scrypt-hash op. Als je het token kwijtraakt, trek het dan in en genereer een nieuw token.
Er is telkens maar één SCIM-token actief. Een nieuw token genereren vervangt het vorige.
::: warning Token opnieuw uitgegeven na upgrade
Verouderde SCIM-tokens zonder versiebeheer worden afgewezen. Na het upgraden naar een release die `so_scim_v2_...`-tokens uitgeeft, genereert u een nieuw token en werkt u uw identiteitsprovider bij voordat u de inrichting hervat.
:::
### Een token intrekken {#revoking-a-token}
`DELETE /api/v1/enterprise/scim/token` trekt het huidige SCIM-token in. Dit eindpunt vereist ook `users:manage`.
`DELETE /api/v1/enterprise/scim/token` trekt het huidige SCIM-token in. Het heeft dezelfde volledige ingebouwde beheerdersvereiste als het genereren van tokens.
### Rate limiting {#rate-limiting}
@@ -279,7 +284,7 @@ Het SCIM-verzoek bevatte geen `Authorization: Bearer <token>`-header. Controleer
### 401 "Invalid token" {#_401-invalid-token}
Het token komt niet overeen met de opgeslagen hash. Dit gebeurt als het token is ingetrokken en opnieuw gegenereerd. Werk het token bij in de provisioning-instellingen van je IdP.
Het token heeft een onjuiste indeling, gebruikt het verouderde formaat zonder versiebeheer of komt niet overeen met de opgeslagen hash. Genereer een actueel `so_scim_v2_...`-token en werk het token bij in de inrichtingsinstellingen van uw IdP.
### 401 "SCIM not configured" {#_401-scim-not-configured}
+90 -162
View File
@@ -1,8 +1,9 @@
---
description: "Handleiding voor beveiligingsverharding van SnapOtter. Containerbeveiliging, netwerkisolatie, Docker-secrets, Kubernetes-implementatie en compliance-artefacten."
i18n_source_hash: 986f7658430c
i18n_provenance: human
i18n_output_hash: 2131ba905ef5
i18n_source_hash: 9ff337fa0417
i18n_provenance: machine
i18n_output_hash: 9637a13165d0
i18n_hash_version: 2
---
# Beveiliging & verharding {#security-hardening}
@@ -11,133 +12,42 @@ SnapOtter verwerkt bestanden volledig op je eigen infrastructuur. Het verstuurt
De container draait als een dedicated niet-root-gebruiker (`snapotter`) met alle Linux-capabilities verwijderd behalve de minimaal vereiste set. Zie voor het volledige beleid voor kwetsbaarheidsonthulling en de beveiligingsarchitectuur [SECURITY.md](https://github.com/snapotter-hq/SnapOtter/blob/main/SECURITY.md) op GitHub.
## Containerverharding {#container-hardening}
## Containerharding {#container-hardening}
De [standaard docker-compose.yml](https://github.com/snapotter-hq/SnapOtter/blob/main/docker/docker-compose.yml) bevat productiebeveiligingsverharding. Hier is een uitsplitsing van elke optie en waarom deze belangrijk is:
De canonieke [CPU](https://github.com/snapotter-hq/SnapOtter/blob/main/docker/docker-compose.yml) en [GPU](https://github.com/snapotter-hq/SnapOtter/blob/main/docker/docker-compose-gpu.yml) Compose-bestanden zijn de bron van de waarheid. Kopieer geen verkort voorbeeld naar productie; implementeer het bestand vanaf de releasetag die u heeft geverifieerd.
```yaml
services:
SnapOtter:
image: snapotter/snapotter:latest
ports:
# Bind to localhost only for internet-facing deployments:
- "127.0.0.1:1349:1349"
volumes:
- SnapOtter-data:/data
- SnapOtter-workspace:/tmp/workspace
environment:
- AUTH_ENABLED=true
- DEFAULT_PASSWORD=change-me-immediately
- RATE_LIMIT_PER_MIN=1000
- DATABASE_URL=postgres://snapotter:snapotter@postgres:5432/snapotter
- REDIS_URL=redis://redis:6379
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
Beide stapels passen de volgende besturingselementen toe:
# --- Resource limits ---
mem_limit: 6g # Prevents runaway memory from crashing the host
memswap_limit: 6g # No swap - fail fast instead of degrading the host
cpus: 4 # Cap CPU usage to 4 cores
pids_limit: 512 # Prevents fork bombs
- Geheugen-, swap-, CPU- en PID-limieten bevatten op hol geslagen native verwerking.
- Elke service laat alle Linux-mogelijkheden vallen. De applicatie voegt alleen `CHOWN, SETUID, SETGID, DAC_OVERRIDE, FOWNER, KILL` toe voor volume-eigendom, de eenrichtings-`gosu`-identiteitsdaling en sierlijke signaaldoorsturing. PostgreSQL en Redis ontvangen alleen de subset die hun officiële toegangspunten nodig hebben.
- `security_opt: [no-new-privileges:true]` voorkomt dat processen in de applicatie-, PostgreSQL- en Redis-containers extra rechten krijgen. Dit blijft compatibel met `gosu`: het toegangspunt begint als root, bereidt de volumes voor en gaat alleen naar de toegewijde `snapotter`-gebruiker.
- PostgreSQL- en Redis-afbeeldingsinvoer wordt vastgezet door digest. De applicatie moet ook worden vastgemaakt aan een geverifieerde releasetag of samenvatting in plaats van aan `latest`.
- Gezondheidscontroles, begrensde JSON-logboekrotatie, duurzame Redis AOF en herstartbeleid worden centraal in de canonieke bestanden gedefinieerd.
# --- Capability restrictions ---
cap_drop:
- ALL # Drop ALL Linux capabilities first
cap_add:
- CHOWN # Needed for volume permission setup
- SETUID # Needed for gosu privilege drop (root -> snapotter)
- SETGID # Needed for gosu privilege drop
- DAC_OVERRIDE # Needed for volume permission setup
- FOWNER # Needed for volume permission setup
Voor een internetgerichte implementatie bindt u poort 1349 aan loopback en beëindigt u TLS bij een onderhouden omgekeerde proxy. Genereer unieke PostgreSQL- en Redis-inloggegevens, sla geheimen op in beveiligde bestanden of in een geheime manager en wijzig het initiële beheerderswachtwoord onmiddellijk.
# --- Logging ---
logging:
driver: json-file
options:
max-size: "50m" # Rotate logs at 50 MB
max-file: "5" # Keep 5 rotated log files
### Waarom `read_only` niet is ingesteld op {#why-read-only-is-not-set}
# --- Health check ---
healthcheck:
test: ["CMD", "curl", "-sf", "--max-time", "5", "http://localhost:1349/api/v1/health"]
interval: 30s
timeout: 5s
start_period: 60s
retries: 3
shm_size: "2gb" # Required for Python ML shared memory
restart: unless-stopped
postgres:
image: postgres:17-alpine
environment:
POSTGRES_USER: snapotter
POSTGRES_PASSWORD: snapotter
POSTGRES_DB: snapotter
volumes:
- SnapOtter-pgdata:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U snapotter"]
interval: 10s
timeout: 5s
retries: 12
start_period: 15s
redis:
image: redis:8-alpine
command: ["redis-server", "--maxmemory-policy", "noeviction", "--appendonly", "yes"]
volumes:
- SnapOtter-redisdata:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 12
start_period: 10s
volumes:
SnapOtter-data:
SnapOtter-workspace:
SnapOtter-pgdata:
SnapOtter-redisdata:
```
### Waarom `no-new-privileges` niet is ingesteld {#why-no-new-privileges-is-not-set}
`security_opt: [no-new-privileges:true]` is bewust weggelaten. De entrypoint start als root om het volume-eigenaarschap te herstellen en zakt dan via [gosu](https://github.com/tianon/gosu), dat setuid vereist, naar de `snapotter`-gebruiker. Zodra de privilegeverlaging is voltooid, draait het proces als `snapotter` met alle capabilities behalve de vijf hierboven genoemde verwijderd.
Als je Kubernetes of Dockers `--user`-vlag gebruikt om rechtstreeks als niet-root te draaien (met omzeiling van gosu), is `no-new-privileges` veilig om in te schakelen.
### Waarom `read_only` niet is ingesteld {#why-read-only-is-not-set}
`read_only: true` is niet ingesteld omdat PUID/PGID-remapping bij het opstarten naar `/etc/passwd` en `/etc/group` schrijft. Als je Dockers `--user`-vlag of Kubernetes `runAsUser` gebruikt in plaats van PUID/PGID, kun je veilig een alleen-lezen root-bestandssysteem inschakelen.
`read_only: true` is niet ingesteld omdat het opnieuw toewijzen van PUID/PGID bij het opstarten naar `/etc/passwd` en `/etc/group` schrijft. Als u Docker's `--user`-vlag of Kubernetes `runAsUser` gebruikt in plaats van PUID/PGID, kunt u veilig een alleen-lezen rootbestandssysteem inschakelen.
## Netwerkisolatie {#network-isolation}
Tijdens normaal gebruik maakt de container **nul uitgaande netwerkverbindingen**. Alle bestandsverwerking gebeurt lokaal met gebundelde bibliotheken.
Bestandsverwerking is lokaal, maar een standaardinstallatie is **geen uitgaand systeem**. Anonieme productanalyses gebruiken PostHog en crashrapportage gebruikt Sentry wanneer telemetrie is ingeschakeld. Stel `SNAPOTTER_TELEMETRY=0` in (of schakel analyses uit onder Instellingen > Systeem > Privacy) om beide uit te schakelen. SnapOtter neemt nooit geüploade bestanden, bestandsnamen, OCR-uitvoer, documenttekst of andere bestandsinhoud op in deze gebeurtenissen.
```
Browser --> Reverse Proxy (TLS) --> SnapOtter container --> (nothing)
```
Ander uitgaand verkeer is functiegestuurd: AI-bundel-/modelinstallatie downloadt ondertekende release-invoer; URL-import haalt een door de gebruiker aangevraagde openbare URL op; en expliciet geconfigureerde OIDC, SAML, OpenTelemetry, webhooks, S3-compatibele opslag of soortgelijke integraties maken contact met de door de beheerder gekozen bestemmingen. Modeldownloads tijdens runtime zijn standaard uitgeschakeld. Stel `SNAPOTTER_ALLOW_MODEL_DOWNLOAD=1` alleen in om automatische fallback-downloads expliciet in te schakelen. Met een [offlinebundelimport](/nl/guide/deployment) kunnen AI-functies worden ingericht zonder uitgaand runtimemodel.
De enige uitzondering is **AI-modeldownloads**: wanneer een gebruiker een AI-featurebundel via de UI installeert, downloadt de container het vooraf gebouwde bundelarchief van Hugging Face, plus enkele individuele modelbestanden van GitHub Releases, Google Storage en PyPI. Deze downloads gebeuren één keer per bundel en worden opgeslagen in het `/data`-volume.
**Firewall-aanbevelingen:**
**Firewallaanbevelingen:**
| Scenario | Uitgaande regel |
|Scenario|Uitgaande regel|
|---|---|
| Air-gapped (geen AI) | Blokkeer al het uitgaande verkeer van de container |
| AI-bundels nodig | Sta HTTPS toe naar `huggingface.co`, `*.xethub.hf.co`, `cdn-lfs.huggingface.co`, `github.com`, `objects.githubusercontent.com`, `storage.googleapis.com`, `pypi.org`, `files.pythonhosted.org` tijdens de installatie, blokkeer daarna |
| Na AI-installatie | Blokkeer al het uitgaande verkeer - modellen worden lokaal gecachet |
|Luchtopening|Stel `SNAPOTTER_TELEMETRY=0` en `SNAPOTTER_ALLOW_MODEL_DOWNLOAD=0` in, gebruik offline AI-bundelimport, schakel URL-import en externe integraties uit en blokkeer vervolgens uitgaand verkeer|
|Standaardtelemetrie|Sta de PostHog- en Sentry-eindpunten toe die worden vermeld in uw browser-/netwerklogboeken; schakel telemetrie uit als het beleid dit niet toestaat|
|AI-bundels nodig|Sta tijdens de installatie HTTPS naar `huggingface.co, *.xethub.hf.co, cdn-lfs.huggingface.co, github.com, objects.githubusercontent.com, storage.googleapis.com, pypi.org, files.pythonhosted.org` toe; blokkeer vervolgens die hosts|
|Externe integraties|Alleen de exacte door de beheerder geconfigureerde OIDC/SAML/OTLP/webhook/object-storage-bestemmingen toestaan|
Bundelarchieven worden geserveerd vanaf Hugging Faces Xet-opslag, die parallel over de `*.xethub.hf.co`-endpoints overdraagt en wat multi-GB-bundeldownloads snel maakt. Als je firewall `huggingface.co` toestaat maar `*.xethub.hf.co` blokkeert, slagen installaties nog steeds maar vallen ze terug op een tragere single-stream-download, dus zet de Xet-hosts op de allowlist om op het snelle pad te blijven. Volledig offline installaties kunnen dit alles overslaan en in plaats daarvan [Offline Bundelimport](/nl/guide/deployment) gebruiken.
Bundelarchieven worden geleverd vanuit de Xet-opslag van Hugging Face, die parallel wordt overgedragen via de `*.xethub.hf.co`-eindpunten en waardoor downloads van bundels van meerdere GB snel verlopen. Als uw firewall `huggingface.co` toestaat maar `*.xethub.hf.co` blokkeert, slagen de installaties nog steeds, maar vallen ze terug op een langzamere download in één stream. Zet daarom de Xet-hosts op de toelatingslijst om op het snelle pad te blijven. Bij volledig offline installaties kunt u dit allemaal overslaan en in plaats daarvan [Offline Bundle Import](/nl/guide/deployment) gebruiken.
Zie voor de configuratie van de reverse proxy (Nginx, Traefik, Caddy, Cloudflare Tunnels) de [Implementatiehandleiding](/nl/guide/deployment#reverse-proxy).
Voor reverse proxy-configuratie (Nginx, Traefik, Caddy, Cloudflare Tunnels), zie de [Implementatiehandleiding](/nl/guide/deployment#reverse-proxy).
## Docker-secrets {#docker-secrets}
@@ -257,83 +167,101 @@ Zie voor de dimensionering van resources [Hardwarevereisten](/nl/guide/deploymen
## Back-up en herstel {#backup-and-recovery}
Persistente staat is verdeeld over twee volumes:
De productie Compose-stack definieert vier volumes. Stop het binnendringen en laat actieve taken voltooien voordat u een gecoördineerde back-up maakt, zodat PostgreSQL, Redis en de bestandsstatus hetzelfde tijdstip beschrijven.
| Volume | Inhoud | Kritiek? |
|Volume|Inhoud|Herstelbehandeling|
|---|---|---|
| `SnapOtter-pgdata` | PostgreSQL-database (gebruikers, instellingen, pijplijnen, jobs, auditlog) | Ja |
| `/data` (app-volume) | Door gebruikers geüploade bestanden, AI-modellen, Python-venv | Gedeeltelijk (zie hieronder) |
|`SnapOtter-pgdata`|PostgreSQL-gebruikers, instellingen, pijplijnen, taken, metagegevens van bestanden en auditlogboek|Kritisch; gebruik een fail-fast logische dump voor draagbaar herstel|
|`SnapOtter-data`|Opgeslagen bibliotheekobjecten, logboeken en AI-status (`/data/files, /data/logs, /data/ai, /data/ai/venv`)|Maak een back-up van het hele volume; om ruimte te besparen, laat u opzettelijk alle AI-statussen weg en installeert u de bundels opnieuw|
|`SnapOtter-redisdata`|Redis AOF voor duurzame BullMQ-wachtrijstatus|Maak een back-up nadat u de app hebt gepauzeerd en `SAVE` hebt geforceerd; vereist om het werk in de wachtrij precies te hervatten|
|`SnapOtter-workspace`|Tijdelijke objectopslagsleutels (`/tmp/workspace/uploads, /tmp/workspace/outputs`)|Maak geen back-up nadat alle taken zijn leeggemaakt of geannuleerd; gooi het nooit weg terwijl er banen actief zijn|
Binnen het `/data`-volume:
| Pad | Inhoud | Kritiek? |
|---|---|---|
| `/data/uploads/`, `/data/outputs/` | Gebruikersbestanden en verwerkingsresultaten | Ja |
| `/data/ai/` | Gedownloade AI-modelbestanden | Nee (opnieuw te downloaden) |
| `/data/venv/` | Python virtual environment | Nee (opnieuw gebouwd bij start) |
Bij Compose worden volumenamen normaal gesproken voorafgegaan door de projectnaam. Los het echte bronvolume op vanuit de gekoppelde container in plaats van aan te nemen dat een weergavenaam zoals `SnapOtter-data` de Docker-volumenaam is.
### Databaseback-up {#database-backup}
Gebruik `pg_dump` om de database te back-uppen terwijl de stack draait:
Gebruik het aangepaste archiefformaat van PostgreSQL en verifieer het archief voordat u de back-up als voltooid beschouwt:
```bash
# Dump the database
docker exec SnapOtter-postgres pg_dump -U snapotter snapotter > backup.sql
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 database
cat backup.sql | docker exec -i SnapOtter-postgres psql -U snapotter snapotter
# Restore only into a fresh/disposable target first; any SQL error fails the command.
docker exec -i SnapOtter-postgres \
pg_restore --exit-on-error --clean --if-exists --no-owner \
-U snapotter -d snapotter < snapotter.dump
```
Stop anders de stack en maak een snapshot van het `SnapOtter-pgdata`-volume:
Test elke back-up door deze terug te zetten naar een geïsoleerde stapel, databaserecords en bestandscontrolesommen te controleren en de toepassing te starten. De `tests/qa/backup-restore-drill.sh` van de repository automatiseert de vrijgavepoort tegen een expliciete `QA_IMAGE`.
Als uw platform in plaats daarvan crash-consistente volume-snapshots maakt, stop dan eerst de hele stack en maak een snapshot van alle kritieke volumes als één set. Een onbewerkte kopie van de PostgreSQL-gegevensmap uit een actieve container is geen ondersteunde logische back-up.
### Bestands- en wachtrijback-up {#file-and-queue-backup}
Pauzeer de toepassing voordat u bestands- en wachtrijvolumes vastlegt. Gebruik `docker inspect` om de daadwerkelijke volumenaam om te zetten, Redis te dwingen de huidige status te behouden en te archiveren met behoud van eigendom en machtigingen:
```bash
docker compose down
docker run --rm -v SnapOtter-pgdata:/data -v $(pwd)/backup:/backup \
alpine tar czf /backup/snapotter-pgdata.tar.gz -C /data .
docker stop SnapOtter
docker exec SnapOtter-redis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning SAVE
docker stop SnapOtter-redis
DATA_VOLUME="$(docker inspect SnapOtter --format '{{range .Mounts}}{{if eq .Destination "/data"}}{{.Name}}{{end}}{{end}}')"
REDIS_VOLUME="$(docker inspect SnapOtter-redis --format '{{range .Mounts}}{{if eq .Destination "/data"}}{{.Name}}{{end}}{{end}}')"
install -d -m 700 backup
docker run --rm -v "$DATA_VOLUME:/source:ro" -v "$PWD/backup:/backup" \
alpine:3.22@sha256:14358309a308569c32bdc37e2e0e9694be33a9d99e68afb0f5ff33cc1f695dce tar czf /backup/snapotter-data.tar.gz -C /source .
docker run --rm -v "$REDIS_VOLUME:/source:ro" -v "$PWD/backup:/backup" \
alpine:3.22@sha256:14358309a308569c32bdc37e2e0e9694be33a9d99e68afb0f5ff33cc1f695dce tar czf /backup/snapotter-redis.tar.gz -C /source .
sha256sum backup/snapotter-*.tar.gz > backup/SHA256SUMS
```
### Back-up van gebruikersbestanden {#user-files-backup}
Start Redis opnieuw vóór de toepassing. Als u opzettelijk `/data/ai` uitsluit, verwijder dan de hele AI-subboom in plaats van een `installed.json`-record te behouden zonder de modellen of virtuele omgeving ervan. Houd back-upbestanden gecodeerd, met toegangscontrole en gescheiden van de host waarop SnapOtter draait.
```bash
# Snapshot the app data volume (excluding re-downloadable AI models)
docker run --rm -v SnapOtter-data:/data -v $(pwd)/backup:/backup \
alpine tar czf /backup/snapotter-files.tar.gz \
--exclude='ai' --exclude='venv' -C /data .
```
AI-modellen tellen op tot ongeveer 24 GB over alle bundels. Aangezien ze opnieuw te downloaden zijn, sluit je `/data/ai/` en `/data/venv/` uit van back-ups om ruimte te besparen. Alleen de database en gebruikersbestanden zijn kritiek.
## Compliance-artefacten {#compliance-artifacts}
## Nalevingsartefacten {#compliance-artifacts}
Elke SnapOtter-release bevat de volgende beveiligingsartefacten:
| Artefact | Formaat | Waar te vinden |
| Artefact | Formaat | Waar je het kunt vinden |
|---|---|---|
| SBOM (CycloneDX) | JSON | [GitHub Release](https://github.com/snapotter-hq/SnapOtter/releases)-asset: `snapotter-v{version}-sbom.cdx.json` |
| SBOM (SPDX) | JSON | [GitHub Release](https://github.com/snapotter-hq/SnapOtter/releases)-asset: `snapotter-v{version}-sbom.spdx.json` |
| Kwetsbaarheidsscan | Trivy JSON | [GitHub Release](https://github.com/snapotter-hq/SnapOtter/releases)-asset: `snapotter-v{version}-trivy.json` |
| Kwetsbaarheidsscan | SARIF | [GitHub Security](https://github.com/snapotter-hq/SnapOtter/security)-tabblad |
| Statische analyse | CodeQL (JS/TS + Python) | [GitHub Security](https://github.com/snapotter-hq/SnapOtter/security)-tabblad, draait wekelijks + per PR |
| Dependency review | GitHub-native | Controle per PR, faalt op toevoegingen met hoge ernst |
| Python-dependency-audit | pip-audit | CI-runlog bij elke push |
| Onderwerpbinding vrijgeven | Canonieke JSON + GitHub-attest | [GitHub-vrijgave](https://github.com/snapotter-hq/SnapOtter/releases) item: `snapotter-v{version}-release-subjects.json` |
| Archief SBOM | CycloneDX en SPDX JSON | Activa vrijgeven: `snapotter-v{version}-archive-linux-{arch}-sbom.{cdx,spdx}.json` |
| Afbeelding SBOM | CycloneDX en SPDX JSON | Activa vrijgeven: `snapotter-v{version}-image-linux-{arch}-sbom.{cdx,spdx}.json` |
| Kwetsbaarheidsscans | Trivy JSON | Activa vrijgeven met overeenkomende `archive-linux-{arch}`- of `image-linux-{arch}`-voorvoegsels |
| Kwetsbaarheidsscan | SARIF | Tabblad [GitHub Beveiliging](https://github.com/snapotter-hq/SnapOtter/security). |
| Statische analyse | CodeQL (JS/TS + Python) | Tabblad [GitHub Beveiliging](https://github.com/snapotter-hq/SnapOtter/security), wordt wekelijks + per PR uitgevoerd |
| Afhankelijkheidsbeoordeling | GitHub eigen | Controle per PR, mislukt bij zeer ernstige toevoegingen |
| Python-afhankelijkheidsaudit | pip-audit | CI voert log uit bij elke druk |
| Beveiligingsbeleid | Markdown | [SECURITY.md](https://github.com/snapotter-hq/SnapOtter/blob/main/SECURITY.md) in de repository |
| Dependency-updates | Dependabot | Geautomatiseerde wekelijkse PR's voor npm, pip, Docker, Actions |
| Afhankelijkheidsupdates | Dependabot | Geautomatiseerde wekelijkse PR's voor npm, pip, Docker, acties |
**Je eigen scan uitvoeren:**
**Uw eigen scan uitvoeren:**
Download de SBOM van de release en scan deze met je voorkeurstool:
Download het release-onderwerpmanifest en controleer of dit is bevestigd door de releaseworkflow:
```bash
gh attestation verify snapotter-v2.1.0-release-subjects.json \
--repo snapotter-hq/SnapOtter \
--signer-workflow snapotter-hq/SnapOtter/.github/workflows/release.yml
```
Het manifest registreert `releaseTag`, `releaseCommit` en `workflowTriggerCommit` afzonderlijk. Controleer of `releaseCommit` de commit is die is gepeld uit de onveranderlijke tag en verifieer vervolgens de SHA-256-samenvatting van het archief, de afbeelding, SBOM of de scan die u gebruikt, ten opzichte van de vermelding ervan in `subjects`. Dit onderscheid is opzettelijk gemaakt: het uitchecken van een nieuw gemaakte release commit verandert niets aan de commit-identiteit in de OIDC-referentie van de workflow.
U kunt ook een gedownloade SBOM of de afbeelding rechtstreeks scannen:
```bash
# Scan with Grype using the CycloneDX SBOM
grype sbom:snapotter-v1.17.2-sbom.cdx.json
grype sbom:snapotter-v2.1.0-image-linux-amd64-sbom.cdx.json
# Scan with Trivy using the SPDX SBOM
trivy sbom snapotter-v1.17.2-sbom.spdx.json
trivy sbom snapotter-v2.1.0-image-linux-amd64-sbom.spdx.json
# Scan the Docker image directly
trivy image snapotter/snapotter:1.17.2
trivy image snapotter/snapotter:2.1.0
```
::: info
De SBOM en kwetsbaarheidsscan weerspiegelen de exacte image die voor die release is gepubliceerd. AI-modelbundels die na implementatie zijn geïnstalleerd, zijn niet in de SBOM opgenomen omdat ze tijdens runtime worden gedownload.
::: info
Afbeelding SBOMs en scans weerspiegelen de exacte architectuurspecifieke afbeelding die voor die release is gepubliceerd. Archief SBOMs en scans beschrijven het vooraf gebouwde archief afzonderlijk. AI-modelbundels die na de implementatie zijn geïnstalleerd, zijn niet opgenomen in deze SBOMs omdat ze tijdens runtime worden gedownload.
:::
+6 -2
View File
@@ -11,7 +11,7 @@ SnapOtter verwerkt bestanden over vijf modaliteiten: afbeelding, video, audio, P
## Afbeeldingsformaten {#image-formats}
SnapOtter ondersteunt 55+ afbeeldingsformaten voor invoer en 13 formaten voor uitvoer.
SnapOtter ondersteunt 55+ afbeeldingsformaten voor invoer en 17 formaten voor uitvoer.
## Invoerformaten {#input-formats}
@@ -104,7 +104,7 @@ SnapOtter ondersteunt 55+ afbeeldingsformaten voor invoer en 13 formaten voor ui
| PAM | .pam | Sharp (native) | Willekeurige map |
| PFM | .pfm | Sharp (native) | Float-map |
## Uitvoerformaten (13) {#output-formats-13}
## Uitvoerformaten (17) {#output-formats-13}
| Formaat | Encoder | Kwaliteitsregeling | Beschikbaar in |
|--------|---------|----------------|-------------|
@@ -121,6 +121,10 @@ SnapOtter ondersteunt 55+ afbeeldingsformaten voor invoer en 13 formaten voor ui
| ICO | ImageMagick CLI | Lossless | Convert-tool |
| JP2 | opj_compress CLI | Compressieverhouding | Convert-tool |
| QOI | Inline codec | Lossless | Convert-tool |
| PSD | ImageMagick CLI | Lossless | Convert-tool |
| PPM | ImageMagick CLI | Lossless | Convert-tool |
| EPS | ImageMagick CLI | Lossless | Convert-tool |
| TGA | ImageMagick CLI | Lossless | Convert-tool |
## Videoformaten {#video-formats}
+13 -10
View File
@@ -1,8 +1,9 @@
---
description: "Beheer gebruikers, ingebouwde en aangepaste rollen, permissies, API-sleutels, teams, sessies en het auditlogboek in SnapOtter."
i18n_source_hash: 5e28af686c96
i18n_source_hash: bea8955f3aff
i18n_provenance: human
i18n_output_hash: ddd4d1d21c1b
i18n_output_hash: cfde44218e7c
i18n_hash_version: 2
---
# Gebruikers, rollen en permissies {#users-roles-permissions}
@@ -82,12 +83,12 @@ Alle 17 permissies. Volledige controle over de instantie.
| `pipelines:all` | Pipelines van alle gebruikers bekijken en beheren |
| `settings:read` | Instantie-instellingen bekijken |
| `settings:write` | Instantie-instellingen wijzigen |
| `users:manage` | Gebruikersaccounts aanmaken, bijwerken en verwijderen |
| `users:manage` | Creëer en beheer gebruikersaccounts binnen de bevoegdheidsgrens van de actor |
| `teams:manage` | Teams aanmaken, bijwerken en verwijderen |
| `features:manage` | AI-featurebundels installeren en beheren |
| `system:health` | Toegang tot health- en readiness-endpoints |
| `audit:read` | Het auditlogboek bekijken en rollen weergeven |
| `compliance:manage` | GDPR-lifecycle en compliancefuncties beheren |
| `compliance:manage` | Beheer AVG-levenscyclus- en compliancefuncties; destructieve gebruikersbewerkingen blijven autoriteitsgebonden |
| `webhooks:manage` | Uitgaande webhooks configureren |
| `security:manage` | Beveiligingsinstellingen beheren (IP-allowlist, SSO-afdwinging) |
@@ -110,15 +111,17 @@ curl -X POST http://localhost:1349/api/v1/roles \
Rolnamen moeten 2-30 tekens zijn, kleine letters, alfanumeriek met koppeltekens en underscores.
### Voor beheerders gereserveerde permissies {#admin-reserved-permissions}
### Gedelegeerde bestuursgrenzen {#delegated-administration-boundaries}
Drie permissies zijn gereserveerd voor ingebouwde rollen en kunnen niet aan aangepaste rollen worden toegewezen:
Alle 17 machtigingen kunnen worden gedelegeerd via aangepaste rollen, maar een beheerdersmachtiging maakt die rol niet gelijkwaardig aan de ingebouwde `admin`-rol. Gebruikersmutaties geautoriseerd door `users:manage`, destructieve bewerkingen geautoriseerd door `compliance:manage`, en beheer van aangepaste rollen geautoriseerd door `security:manage` worden begrensd door de huidige autoriteit van de actor:
- `compliance:manage`
- `webhooks:manage`
- `security:manage`
- Ingebouwde rollen volgen `admin` > `editor` > `user`; aangepaste rollen staan onder ingebouwde rollen.
- De machtigingen van het doelwit moeten worden vastgelegd in de **effectieve** machtigingen van de acteur. Een API-sleutel met een bereik kan daarom geen machtigingen uitoefenen die zijn weggelaten uit het bereik ervan.
- De tooltoegang van een doelrol moet beperkt zijn tot de tooltoegang van de actor zelf.
- Een uitgeschakeld account wordt gecontroleerd aan de hand van de oorspronkelijke rol wanneer die rol wordt geregistreerd als `disabled:<original-role>`.
- Het verwijderen van een aangepaste rol vereist ook de bevoegdheid om de ingebouwde `user`-fallback toe te wijzen; gehandicapte leden blijven uitgeschakeld als `disabled:user`.
De rollen-API weigert elk verzoek dat deze permissies bevat. Alleen de ingebouwde rol `admin` heeft er toegang toe.
De algemene inloggegevens en configuratie zijn strenger: voor het uitgeven of intrekken van het SCIM-token en het importeren van de instanceconfiguratie is de ingebouwde `admin`-rol met volledige effectieve beheerdersbevoegdheid vereist.
### Permissies op toolniveau {#tool-level-permissions}