Compare commits

..
Author SHA1 Message Date
Masterluke77 e67df61989 docs: prepare Vendoo 1.34.1 secure source import 2026-07-09 11:05:01 +02:00
1495 changed files with 230 additions and 244369 deletions
-27
View File
@@ -1,27 +0,0 @@
.git
.gitignore
.env
.env.*
!.env.example
node_modules
npm-debug.log*
*.log
*.db
*.db-*
*.sqlite
*.sqlite3
backups
operations
logs
uploads
runtime
data
local-ai/comfyui
local-ai/downloads
local-ai/.env.local-flux
MockupDesign
*.zip
FILE_CHECKSUMS_SHA256.txt
release-output
.vendoo-github-state.json
operations/first-admin-code.txt
+23 -79
View File
@@ -1,89 +1,33 @@
# Vendoo 1.37.0 Beispielkonfiguration für Windows, Docker und NAS
# Diese Datei enthält ausschließlich Platzhalter. Für den Betrieb als .env kopieren.
# Niemals eine produktive .env in Release-ZIPs, Git oder Support-Logs aufnehmen.
NODE_ENV=development
HOST=127.0.0.1
PORT=8124
PUBLIC_BASE_URL=http://localhost:8124
TRUST_PROXY=0
COOKIE_SECURE=false
COOKIE_SAMESITE=lax
ALLOWED_ORIGINS=http://localhost:8124
DATA_DIR=./data
DB_PATH=./db/vendoo.db
UPLOAD_DIR=./uploads
BACKUP_DIR=./backups
SESSION_SECRET=
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
OPENROUTER_API_KEY=
OLLAMA_URL=http://localhost:11434
LOCAL_IMAGE_ENABLED=false
LOCAL_IMAGE_URL=http://127.0.0.1:8188
LOCAL_IMAGE_TOKEN=
LOCAL_IMAGE_WORKFLOW_PATH=local-ai/workflows/vendoo_flux_schnell_api.json
LOCAL_IMAGE_INSTALL_PATH=local-ai/comfyui
LOCAL_IMAGE_REQUIRE_TOKEN=true
LOCAL_IMAGE_ALLOW_REMOTE=false
ETSY_API_KEY=
ETSY_CLIENT_SECRET=
EBAY_CLIENT_ID=
EBAY_CLIENT_SECRET=
EBAY_RU_NAME=
EBAY_SANDBOX=true
SMTP_HOST=smtp.example.de
SMTP_HOST=
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=
SMTP_PASS=
SMTP_FROM=Vendoo <vendoo@example.de>
SMTP_PASSWORD=
SMTP_FROM=
PORT=8124
# Docker veröffentlicht standardmäßig nur an 127.0.0.1. Für NAS-Reverse-Proxy ggf. bewusst anpassen.
VENDOO_PUBLISH_ADDRESS=127.0.0.1
VENDOO_HOST_PORT=8124
# Vom Smartphone erreichbare Basis-URL für QR-Fotouploads.
# Beispiel im LAN: http://192.168.178.50:8124
# Öffentlich ausschließlich per HTTPS verwenden.
PUBLIC_BASE_URL=
# Nur für den geführten VPS-Modus; setup.sh trägt die Domain automatisch ein.
VENDOO_DOMAIN=
# Optional: öffentliche JSON-Manifest-URL für die Updateprüfung
VENDOO_UPDATE_MANIFEST_URL=
# Server-, Mehrbenutzer- und Deployment-Sicherheit (1.37.0)
# Standardmäßig nur auf diesem PC erreichbar. Für LAN bewusst auf 0.0.0.0 setzen.
VENDOO_BIND_HOST=127.0.0.1
# Kommagetrennte zusätzliche Hostnamen/IPs, z. B. vendoo.intern,192.168.178.50
VENDOO_ALLOWED_HOSTS=
# Kommagetrennte zusätzliche Browser-Ursprünge, jeweils mit Protokoll und Port
VENDOO_ALLOWED_ORIGINS=
# Nur hinter einem korrekt konfigurierten Reverse Proxy aktivieren
VENDOO_TRUST_PROXY=false
VENDOO_SESSION_DAYS=3
VENDOO_SESSION_IDLE_MINUTES=120
VENDOO_READ_RATE_LIMIT=360
VENDOO_MUTATION_RATE_LIMIT=120
# Produktionsbereitstellung 1.37.0
# Mindestens 32 zufällige Zeichen. Wird beim ersten Admin-Setup abgefragt.
VENDOO_SETUP_TOKEN=
VENDOO_REQUIRE_SETUP_TOKEN=true
VENDOO_COOKIE_SECURE=auto
VENDOO_COOKIE_SAMESITE=lax
# Konkrete Extension-Origins, z. B. chrome-extension://abcdefghijklmnop...
VENDOO_EXTENSION_ORIGINS=
VENDOO_ALLOW_ANY_EXTENSION_ORIGIN=false
# Optionale getrennte Laufzeitpfade. Windows kann die Standardwerte leer lassen.
VENDOO_DATA_DIR=
VENDOO_DB_PATH=
VENDOO_UPLOADS_DIR=
VENDOO_BACKUP_DIR=
VENDOO_OPERATIONS_DIR=
VENDOO_LOG_DIR=
# Docker setzt automatisch /app/data/config/vendoo.env; lokal bleibt dieser Wert leer.
VENDOO_CONFIG_PATH=
# Security, Secrets & Observability (1.37.0)
# Normalerweise automatisch verwaltet; keine manuelle Bearbeitung erforderlich.
# VENDOO_SECRETS_PATH=/app/data/config/secrets.enc.json
# VENDOO_MASTER_KEY_FILE=/app/data/config/master.key
# Optional: externer 32-Byte-Master-Key als Base64 oder 64 Hex-Zeichen.
# VENDOO_MASTER_KEY=
VENDOO_JSON_LOGS=true
SMTP_TLS_REJECT_UNAUTHORIZED=true
ETSY_API_KEY=
ETSY_CLIENT_SECRET=
EBAY_CLIENT_ID=
EBAY_CLIENT_SECRET=
EBAY_RUNAME=
EBAY_SANDBOX=true
-1
View File
@@ -1 +0,0 @@
* @Masterluke77
-27
View File
@@ -1,27 +0,0 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
time: '05:00'
timezone: Europe/Berlin
open-pull-requests-limit: 5
groups:
npm-production:
dependency-type: production
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
time: '05:30'
timezone: Europe/Berlin
open-pull-requests-limit: 5
- package-ecosystem: docker
directory: /
schedule:
interval: monthly
time: '06:00'
timezone: Europe/Berlin
open-pull-requests-limit: 5
-20
View File
@@ -1,20 +0,0 @@
## Änderung
<!-- Was wurde geändert und warum? -->
## Sicherheit und Daten
- [ ] Keine `.env`, Tokens, Datenbanken, Uploads, Backups, Logs oder Modelle enthalten
- [ ] Bestehende Benutzer- und Artikeldaten bleiben erhalten
- [ ] Originalbilder werden nicht überschrieben
- [ ] FASHN VTON / Virtual Try-on wurde nicht wieder eingeführt
## Prüfung
- [ ] `npm ci`
- [ ] `npm run verify:git`
- [ ] `npm run check`
- [ ] `npm run verify:architecture`
- [ ] `npm run verify:deployment`
- [ ] `npm run verify:db`
- [ ] Windows-/Docker-/Browser-Abnahme dokumentiert oder ausdrücklich als offen markiert
-89
View File
@@ -1,89 +0,0 @@
name: Vendoo CI
on:
push:
branches: [main, develop, 'feature/**', 'release/**', 'hotfix/**']
pull_request:
branches: [main, develop]
permissions:
contents: read
concurrency:
group: vendoo-ci-${{ github.ref }}
cancel-in-progress: true
jobs:
quality:
name: Syntax, Sicherheit und Release-Gates
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- name: Repository auschecken
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Node.js 22 aktivieren
uses: actions/setup-node@v4
with:
node-version: '22.x'
cache: npm
- name: Abhängigkeiten reproduzierbar installieren
run: npm ci
- name: Git-Sicherheitsgate
run: npm run verify:git
- name: Git-Sicherheitsgate Regressionstest
run: npm run verify:git-regression
- name: Git-Staging-Filter Regressionstest
run: npm run verify:git-staging
- name: Syntaxprüfung
run: npm run check
- name: Plattformarchitektur und Design Tokens prüfen
run: npm run verify:architecture
- name: Theme Manager, Accessibility und Komponenten-Tokens prüfen
run: npm run verify:themes
- name: Security, Secrets und Observability prüfen
run: npm run verify:security
- name: Auth, Benutzer, Sitzungen und Einstellungen prüfen
run: npm run verify:identity
- name: Deployment-Gate
run: npm run verify:deployment
- name: Persistenten Konfigurationsspeicher prüfen
run: npm run verify:config
- name: Geführte Shell-Installer simulieren
run: npm run verify:installer-shell
- name: Datenbankmigrationen prüfen
run: npm run verify:db
- name: Docker-Compose-Dateien validieren
run: |
cp .env.example .env
python - <<'PY'
from pathlib import Path
p=Path('.env')
s=p.read_text()
s=s.replace('VENDOO_SETUP_TOKEN=', 'VENDOO_SETUP_TOKEN=ci-only-not-a-production-secret-1234567890')
s=s.replace('VENDOO_DOMAIN=', 'VENDOO_DOMAIN=vendoo.example.invalid')
p.write_text(s)
PY
docker compose -f compose.yaml config -q
docker compose -f compose.yaml -f compose.bind-mounts.example.yaml config -q
docker compose -f compose.vps.yaml config -q
rm -f .env
- name: Docker-Image testweise bauen
run: docker build --pull --tag vendoo:ci .
-145
View File
@@ -1,145 +0,0 @@
name: Vendoo Release
on:
release:
types: [published]
permissions:
contents: read
concurrency:
group: vendoo-release-${{ github.event.release.tag_name }}
cancel-in-progress: false
env:
REGISTRY: ghcr.io
IMAGE_NAME: masterluke77/vendoo
jobs:
release-assets:
name: Release-Paket und Prüfsummen
permissions:
contents: write
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Repository auschecken
uses: actions/checkout@v6
- name: Node.js 22 aktivieren
uses: actions/setup-node@v4
with:
node-version: '22.x'
cache: npm
- name: Abhängigkeiten installieren
run: npm ci
- name: Release-Tag gegen Paketversion prüfen
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
EXPECTED="v$(node -p "require('./package.json').version")"
test "$RELEASE_TAG" = "$EXPECTED" || { echo "Release-Tag $RELEASE_TAG passt nicht zu $EXPECTED." >&2; exit 1; }
- name: Vollständige Prüfung
run: |
npm run verify:git
npm run verify:git-regression
npm run verify:git-staging
npm run check
npm run verify:architecture
npm run verify:themes
npm run verify:security
npm run verify:identity
npm run verify:deployment
npm run verify:config
npm run verify:installer-shell
npm run verify:db
- name: Release-Staging erzeugen
run: node tools/build-release.mjs
- name: ZIP und SHA-256 erzeugen
id: package
shell: bash
run: |
PACKAGE_NAME="$(cat release-output/RELEASE_NAME.txt)"
cd release-output
zip -r -9 "${PACKAGE_NAME}.zip" "${PACKAGE_NAME}"
sha256sum "${PACKAGE_NAME}.zip" > "${PACKAGE_NAME}.zip.sha256.txt"
echo "package_name=${PACKAGE_NAME}" >> "$GITHUB_OUTPUT"
- name: Assets an GitHub Release anhängen
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }}
PACKAGE_NAME: ${{ steps.package.outputs.package_name }}
run: |
gh release upload "$TAG" \
"release-output/${PACKAGE_NAME}.zip" \
"release-output/${PACKAGE_NAME}.zip.sha256.txt" \
--clobber
- name: Build-Artefakte sichern
uses: actions/upload-artifact@v4
with:
name: ${{ steps.package.outputs.package_name }}
path: |
release-output/${{ steps.package.outputs.package_name }}.zip
release-output/${{ steps.package.outputs.package_name }}.zip.sha256.txt
if-no-files-found: error
retention-days: 30
container:
name: GHCR-Container veröffentlichen
permissions:
contents: read
packages: write
attestations: write
id-token: write
runs-on: ubuntu-latest
timeout-minutes: 35
steps:
- name: Repository auschecken
uses: actions/checkout@v6
- name: Docker Buildx aktivieren
uses: docker/setup-buildx-action@v3
- name: Bei GHCR anmelden
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Container-Metadaten erzeugen
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}},value=${{ github.event.release.tag_name }}
type=semver,pattern={{major}}.{{minor}},value=${{ github.event.release.tag_name }}
type=raw,value=latest,enable=${{ !github.event.release.prerelease }}
- name: Container bauen und veröffentlichen
id: push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64
provenance: true
sbom: true
- name: Container-Provenienz attestieren
uses: actions/attest@v4
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
+25 -51
View File
@@ -1,4 +1,4 @@
# Secrets and local configuration
# Environment and secrets
.env
.env.*
!.env.example
@@ -8,77 +8,51 @@
*.p12
*.pfx
*.crt
*.cer
# Dependencies
# Node.js
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# SQLite runtime data
# Databases and SQLite runtime files
db/*.db
db/*.db-shm
db/*.db-wal
db/*.sqlite
db/*.sqlite3
*.db-shm
*.db-wal
# User and runtime data
# Runtime data
uploads/*
!uploads/.gitkeep
backups/
backups/*
!backups/.gitkeep
logs/
*.log
tmp/
temp/
sessions/
data/
docker-data/
*.log
# OS and editor files
# Generated files and local state
coverage/
dist/
.cache/
*.pid
*.seed
# Editors and operating systems
.vscode/
.idea/
.DS_Store
Thumbs.db
desktop.ini
.vscode/
.idea/
# Local overrides
# Local Docker overrides
compose.override.yaml
docker-compose.override.yml
# Local AI runtimes and downloaded model data
local-ai/comfyui/
local-ai/downloads/
local-ai/extract-temp/
local-ai/fashn-vton/.venv/
local-ai/fashn-vton/engine/
local-ai/fashn-vton/weights/
local-ai/fashn-vton/outputs/
local-ai/fashn-vton/runtime/
local-ai/fashn-vton/hf-cache/
local-ai/fashn-vton/fashn-vton-*.zip
local-ai/fashn-vton/python311/
local-ai/fashn-vton/uv/
local-ai/fashn-vton/uv-cache/
local-ai/fashn-vton/downloads/
# Local update, rollback and slice archives
updates/
# Operations Center runtime
operations/staging/
operations/updates/
operations/rollback/
operations/apply-*/
operations/pending-operation.json
operations/last-operation.json
# Deployment assistant state
.vendoo-install-mode
runtime/
# Generated deployment and release output
release-output/
*.release.zip
*.release.sha256.txt
.vendoo-github-state.json
# First-run and local installer state
operations/first-admin-code.txt
config/local/
-1
View File
@@ -1 +0,0 @@
Vendoo 1.20.0 image-stack cleanup completed.
-9
View File
@@ -1,9 +0,0 @@
registry=https://registry.npmjs.org/
audit=false
fund=false
strict-ssl=true
prefer-offline=true
fetch-retries=5
fetch-retry-factor=2
fetch-retry-mintimeout=10000
fetch-retry-maxtimeout=120000
-33
View File
@@ -1,33 +0,0 @@
# Vendoo 1.31.0 Ist- und Lückenanalyse
Stand der Prüfung: 09.07.2026
Geprüfte Basis: `Vendoo_Feature_1_31_0_Multiuser_Security_Foundation.zip`
Verifizierte SHA-256 der Basis: `cad2670d663c98964b7c3b4e95e5f6e475a3bcae12921339a0a84576b77d325b`
Die Bewertung basiert auf dem real enthaltenen Code. Paketnamen und Dokumentation wurden nicht als alleiniger Funktionsnachweis verwendet.
| Bereich | Status in 1.31.0 | Reale Fundstelle | Risiko/Lücke | Änderung in 1.32.0 |
|---|---|---|---|---|
| Versionen | bestätigt | `package.json`, Lockfile, UI-Build und Manifest = 1.31.0 | keine | auf 1.32.0 synchronisiert |
| Rollen/RBAC | bestätigt | `lib/security.mjs`, globaler `apiPermissionGuard` | einzelne Sonderrouten bleiben zusätzlich manuell zu beobachten | unverändert erhalten |
| Sessions/Login-Schutz | bestätigt, Setup-Ausnahme riskant | `lib/auth.mjs`, gehashte Tokens, Sperrlogik, Widerruf; `requireAuth` übersprang im Setup-Modus alle APIs | vor erstem Admin waren geschützte API-Routen unnötig offen; kein Offline-Notfallreset für verlorenen letzten Admin | API im Setup-Modus gesperrt; Notfallreset als Folgepunkt dokumentiert |
| CSRF/Cookies | vorhanden | Double-Submit-Cookie und Header, `HttpOnly`, dynamisches `Secure`, `SameSite=lax` | Cookie-Modus nicht konfigurierbar; Proxyannahme nur boolesch/ein Hop | Cookie-Modus konfigurierbar, Proxy-Hops/Scopes unterstützt |
| CORS/Origin | vorhanden, unvollständig | Host-/Origin-Middleware in `server.mjs` | jede Browser-Extension-Origin wurde pauschal akzeptiert | in Produktion nur konkrete Extension-Origins, unsicherer Opt-in separat |
| Audit/Locks | bestätigt | Audit-Log, `resource_locks`, Adminansicht | keine kritische Deployment-Lücke | erhalten |
| Health | teilweise | `/healthz` liefert Prozessstatus | keine Readiness-, DB- oder Schreibpfadprüfung | `/readyz` mit DB- und Volume-Schreibtest |
| Shutdown | fehlt | direkter `app.listen()` ohne Signalbehandlung | WAL/Jobs können beim Containerstopp hart beendet werden | SIGTERM/SIGINT, Server-Close, WAL-Checkpoint, DB-Close |
| Datenbankpfad | unvollständig | fest `db/vendoo.db` im Codeordner | Container-Image und Nutzerdaten nicht sauber trennbar | `VENDOO_DB_PATH` und zentrale Laufzeitpfade |
| Uploadpfad | unvollständig | fest `uploads/` im Codeordner | keine getrennte Persistenz; öffentlich statisch erreichbar | konfigurierbarer Pfad, Zugriff hinter Anmeldung |
| Uploadprüfung | Sicherheitsrisiko | Dateiendung **oder** `image/*` genügte | manipulierbarer MIME-Typ konnte beliebige Endungen umgehen | Endung **und** Bild-MIME erforderlich; Größenlimit bleibt aktiv |
| Backups | bestätigt, aber codegebunden | verifizierte ZIPs mit DB/Uploads in `operations-center.mjs` | Pfade fest an Projektroot; Live-Volume-Kopie nicht dokumentiert | separate Backup-/Operations-Volumes und sichere Stop/Backup/Start-Anleitung |
| Restore/Update | vorhanden, gestuft | Operations Center und `setup.ps1` | Container darf Anwendungscode nicht in-place überschreiben | Docker-Update nur über neues Image; Windows-Update bleibt erhalten |
| Docker/Compose | fehlt | keine entsprechenden Dateien | kein reproduzierbarer NAS-/Produktionsbetrieb | Dockerfile, Compose, Healthcheck, non-root, read-only, Volumes |
| Reverse Proxy | teilweise | Host/Origin, `PUBLIC_BASE_URL`, `trust proxy` | kein fertiger Produktionsleitfaden | HTTPS-/Proxy-Dokumentation und sichere Standardbindung |
| FLUX/ComfyUI | getrennt im Konzept | externer URL-Endpunkt; lokaler Windows-Installer | Bootstrap schreibt in Projektordner und passt nicht zu read-only Container | Container startet standardmäßig ohne FLUX; externer Dienst bleibt optional |
| Browser-Erweiterungen | real vorhanden | Chrome/Edge/Firefox/Safari-Strukturen und Pakete | Remote-Kopplung nutzt weiterhin Login-Cookie statt widerrufbarem Extension-Token | CORS gehärtet; Tokenkopplung bleibt geplanter 1.34.0-Slice |
| UI-Begriffe/Kernbereiche | weitgehend bestätigt | Navigation, Artikel, Galerie, SmartCopy, Publish und Erweiterungen im realen HTML/JS | vollständige Browser-End-to-End-Abnahme nicht statisch beweisbar | keine unnötige UI-Neuentwicklung in diesem Deployment-Slice |
| VTO | entfernt | kein aktiver FASHN-/VTO-Dienst; freier FLUX-Workflow ohne `LoadImage` | historische Dokumente enthalten weiterhin Kontext | keine VTO-Rückkehr |
## Ergebnis
1.31.0 besitzt eine echte Mehrbenutzer- und Sicherheitsgrundlage, war aber noch kein sauber containerisierbarer Produktionsstand. Die Hauptlücken lagen in der festen Kopplung von Code und Nutzerdaten, fehlender Readiness, fehlendem geordneten Shutdown, fehlenden Containerdateien sowie zu breiten Extension-Origin- und Uploadregeln.
@@ -1,22 +0,0 @@
# Vendoo 1.37.0 Start hier
Dieses Paket aktualisiert Vendoo 1.36.0 auf **Vendoo 1.37.0 Security, Secrets & Observability Foundation**.
## Wichtig
- Bestehenden Vendoo-Ordner nicht löschen.
- `.env`, Datenbank, Uploads, Backups, Operations-Daten, `updates/`, FLUX-Modelle und ComfyUI-Daten nicht löschen.
- Den Inhalt des Ordners `vendoo` über die vorhandene Installation kopieren und vorhandene Programmdateien ersetzen.
- Danach `setup.bat` starten und **Update** ausführen.
## Hauptänderungen
- `vendoo.security` ist jetzt ein natives Kernmodul.
- API-Schlüssel und Passwörter werden AES-256-GCM-verschlüsselt gespeichert.
- Bestehende Runtime-Secrets werden mit Sicherungskopie migriert.
- Inline-Skripte und Inline-Eventhandler werden per CSP blockiert.
- Request- und Correlation-IDs sowie strukturierte JSON-Telemetrie sind aktiv.
- Neue Kernel-Routen unterstützen zentrale Input-Schemas.
- Die Sicherheitszentrale zeigt Secret-Provider, CSP- und Requeststatus, aber niemals Secret-Klarwerte.
Lies danach `02_INSTALLATION_UND_ABNAHME.md`.
@@ -1,42 +0,0 @@
# Neue Funktionen in Vendoo 1.37.0
## Verschlüsselter Secret-Speicher
Vendoo speichert freigegebene Zugangsdaten in `secrets.enc.json` mit AES-256-GCM. Der Master-Key liegt getrennt in `master.key`. Beide Dateien befinden sich im persistenten Konfigurationsbereich und werden nicht in Git oder Release-Pakete aufgenommen.
Unterstützt werden unter anderem OpenAI, Anthropic, OpenRouter, Etsy, eBay, SMTP und der externe FLUX-Dienst.
## Sichere Migration
Beim ersten Start werden bekannte Secrets aus der Runtime-Konfiguration erkannt. Vor der Änderung wird eine Datei mit der Endung `.pre-secrets-1.37.0.bak` erzeugt. Anschließend werden die Secret-Werte verschlüsselt gespeichert und aus der Klartext-Konfiguration entfernt.
Ein vorhandenes SMTP-Passwort aus der Datenbank wird ebenfalls in den Secret-Speicher migriert und anschließend aus dem bisherigen Feld entfernt.
## Content Security Policy
- keine Inline-Skripte
- keine Inline-Eventhandler
- Login-Logik in externer Datei
- zentrale Eventdelegation im Hauptfrontend
- `script-src-attr 'none'`
- HSTS in Produktionsumgebungen
Inline-Stile bleiben vorerst für den Legacy-Bestand erlaubt und werden in späteren Modulslices schrittweise entfernt.
## Observability
Jeder Request erhält:
- `X-Vendoo-Request-ID`
- `X-Correlation-ID`
- Dauer, Status und Route in strukturierter JSON-Telemetrie
Die Sicherheitszentrale zeigt aggregierte Werte wie Requestanzahl, aktive Requests, Serverfehler und blockierte Host-/Origin-Anfragen.
## Zentrale Eingabeverträge
Neue Kernel-Routen können ein serverseitiges Input-Schema definieren. Unbekannte Felder, falsche Typen, zu lange Werte und ungültige Formate werden vor dem Handler abgewiesen. Die Berechtigungsprüfung erfolgt vor der Eingabevalidierung.
## Backup-Härtung
Docker-/NAS-Backups enthalten jetzt zusätzlich den persistenten Ordner `config/`. Secret-Speicher und Master-Key werden dadurch immer gemeinsam gesichert und beim Restore gemeinsam wiederhergestellt.
@@ -1,48 +0,0 @@
# Installation und Abnahme Vendoo 1.37.0
## Update einer vorhandenen Windows-Installation
1. Vendoo vollständig schließen.
2. ZIP vollständig entpacken.
3. Den Inhalt des enthaltenen Ordners `vendoo` über die vorhandene Vendoo-Installation kopieren.
4. Das Ersetzen vorhandener Programmdateien bestätigen.
5. Den Zielordner vorher nicht löschen oder leeren.
6. `.env`, Datenbank, Uploads, Backups, Operations-Daten, `updates/`, FLUX-Modelle und ComfyUI-Daten erhalten.
7. `setup.bat` starten.
8. **Update** auswählen.
9. Vendoo starten.
## Automatische Secret-Migration
Beim ersten Start von 1.37.0:
- bekannte Klartext-Secrets werden erkannt,
- eine Sicherung der Runtime-Konfiguration wird erstellt,
- Werte werden verschlüsselt gespeichert,
- die ursprünglichen Secret-Zeilen werden entfernt.
Der neue Speicher liegt standardmäßig unter:
```text
<data>/config/secrets.enc.json
<data>/config/master.key
```
Diese Dateien nicht einzeln zwischen Installationen austauschen. Für Restore oder Umzug müssen beide zusammen mit dem Konfigurationsvolume gesichert werden.
## Abnahme
1. `http://127.0.0.1:8124/readyz` öffnen.
2. `platform-kernel` muss erfolgreich sein.
3. Als Administrator **Admin → Sicherheit** öffnen.
4. Prüfen, dass `Secret-Speicher` den Provider `encrypted-file` zeigt.
5. Prüfen, dass keine Secret-Klarwerte angezeigt werden.
6. AI-/Marktplatz-/SMTP-Einstellungen speichern und Vendoo neu starten.
7. Prüfen, dass die Verbindungen weiterhin als konfiguriert erscheinen.
8. Im Browser-Netzwerk prüfen, dass Antworten `X-Vendoo-Request-ID` und `X-Correlation-ID` enthalten.
9. Login, Benutzerverwaltung, Theme Manager, Artikel, Upload und FLUX Studio testen.
10. Danach `GitHub-Deploy-Assistent.bat` starten, Git-Status prüfen und erst anschließend `PUSH` eingeben.
## Docker/NAS/VPS
Der persistente Konfigurationsbereich `/app/data/config` enthält Runtime-Konfiguration, Secret-Speicher und Master-Key. Das vorhandene `vendoo_config`-Volume beziehungsweise der NAS-Bind-Mount muss erhalten bleiben und in Backups eingeschlossen werden.
@@ -1,36 +0,0 @@
# Ist- und Lückenanalyse Vendoo 1.36.0 zu 1.37.0
## Real bestätigter Ausgangsstand
- modularer Plattformkernel vorhanden
- Theme-Modul nativ, elf Bereiche als Legacy Bridges
- sichere Theme-Tokens und Theme Manager vorhanden
- Request-ID bereits rudimentär vorhanden
- API- und SMTP-Secrets teilweise in Runtime-`.env` oder Datenbank gespeichert
- CSP erlaubte Inline-Skripte
- Login enthielt Inline-JavaScript
- mehrere Inline-Eventhandler waren vorhanden
- Security-Dashboard zeigte Netzwerk, Sessions, Limits und Locks, aber keine Secret-/CSP-/Request-Telemetrie
## Geschlossene Lücken
- nativer Security-Kern
- verschlüsselter Secret-Speicher mit separatem Schlüssel
- sichere Klartextmigration mit Backup
- keine Secret-Rückgabe an Browser
- strikte Script-CSP
- Entfernung aller Inline-Eventhandler im öffentlichen Frontend
- externe Login-Datei
- zentrale Request-/Correlation-IDs
- strukturierte Request-Telemetrie
- zentrale Input-Schema-Grundlage
- Security-Dashboard erweitert
- SMTP-Zertifikatsprüfung standardmäßig aktiviert
## Bewusst verbleibende Lücken
- Inline-Stile im Legacy-Frontend erfordern weiterhin `style-src 'unsafe-inline'`.
- Windows-DPAPI, Docker Secrets und externe Vault-Systeme sind noch keine eigenen Provider.
- Telemetrie ist pro Prozess und noch nicht langfristig persistiert.
- Vollständige Security-Event-Korrelation und Alarmierung folgen später.
- Auth-, User- und Settings-Code befinden sich überwiegend noch im Legacy-Server.
@@ -1,45 +0,0 @@
# Abnahmebericht Vendoo 1.37.0
## Bestanden
- JavaScript-/MJS-Syntax
- Git-Sicherheitsgate
- Git-Sicherheits-Regression
- Git-Staging-Regression
- Theme-Manager-Gate 1.37.0
- Security-Foundation-Gate 1.37.0
- Plattform-Architecture-Gate 1.37.0
- Deployment-Gate 1.37.0
- persistenter Konfigurationsspeicher
- Shell-Installer-Simulation für Docker, NAS und VPS
- 68 Migrationsblöcke gegen frische Datenbank
- 68 Migrationsblöcke gegen bestehende Datenbank
- vorhandener Testdatensatz blieb erhalten
- AES-256-GCM-Ver- und Entschlüsselung
- Klartextmigration mit Sicherung
- Secret-Maskierung
- Ablehnung unbekannter und mehrzeiliger Secrets
- CSP ohne Inline-Skripte und Inline-Eventhandler
- Docker-Backup und Restore schließen `config/` samt Secret-Speicher und Master-Key ein
- Request-/Correlation-ID und Telemetrie
- zwölf Module: zwei nativ, zehn Legacy Bridges
## Nicht als praktisch ausgeführt ausgewiesen
- vollständiger Windows-/PowerShell-Lauf
- Browser-End-to-End-Test unter echtem Windows
- Docker-/NAS-/VPS-Livestart
- Caddy-/TLS-Livetest
- GitHub-Actions-Livelauf
- native `better-sqlite3`-Kompilierung in dieser Sandbox
- Prüfung echter externer AI-, SMTP- und Marktplatzkonten
## Abhängigkeiten
`npm ci --ignore-scripts --no-audit --no-fund` löste die Lockdatei reproduzierbar auf und installierte 151 Pakete. Die native Kompilierung von `better-sqlite3` konnte in der Sandbox nicht abgeschlossen werden, weil GitHub-Prebuilds und Node-Header wegen fehlender DNS-/Netzwerkverbindung nicht geladen werden konnten. Dieser Punkt wird deshalb ausdrücklich nicht als Laufzeittest gewertet.
## Release-Staging
Der bereinigte Vendoo-Release-Stand enthält 397 per SHA-256 erfasste Quelldateien. Alle 397 Prüfsummen wurden im getrennten Release-Staging erfolgreich zurückverifiziert.
Das vollständige Übergabepaket enthält 405 Dateien. Das Paketmanifest erfasst 404 Dateien zuzüglich seiner eigenen Manifestdatei; der enthaltene Vendoo-Ordner umfasst 398 Dateien einschließlich seines eigenen Prüfsummenmanifests.
@@ -1,32 +0,0 @@
# Vendoo Roadmap nach 1.37.0
## 1.38.0 Auth, Users & Settings Native Modules
- Authentifizierung aus `server.mjs` lösen
- Benutzer, Rollen und Sessions in native Module überführen
- Settings-Modul mit zentralen Schemas
- Secret-UI vollständig in das Security-/Settings-Modul integrieren
- standardisierte API-Fehler und Audit-Verträge
## 1.39.0 Listings, Inventory & Media Modules
- Artikel-, Lager- und Medienlogik modularisieren
- Repositories statt direkter DB-Zugriffe in Routes
- Upload-Pipeline mit Magic-Byte- und Bilddecoder-Prüfung
- modulare Frontend-Lebenszyklen
## 1.40.0 Publishing, AI & FLUX Modules
- Plattformadapter und Publishing-Jobs trennen
- AI-Anbieter über Adapterverträge
- FLUX als klar isolierter externer Dienst
- Capability-basierte Extension-Kommunikation
## Spätere Sicherheitsschritte
- DPAPI-/Keychain-/Docker-Secret-Provider
- optionale Vault-Integration
- persistente Security-Event-Telemetrie
- Alarmregeln und Benachrichtigungen
- Entfernung von `style-src 'unsafe-inline'`
- vollständige OWASP-ASVS-L2-Abnahmematrix
@@ -1,404 +0,0 @@
afa423368ca683c5e237931c95c1fce8632af7052eed6a35a37774e6e61e47eb 00_START_HIER.md
fbe36d0040052cfaa31933ce9d191b4abe2f3925641fd65429a56a30e9ddc981 01_NEUE_FUNKTIONEN.md
12bec6fab408a113a31855202e2c12901197e789e54af903d82f160a9c3dafb0 02_INSTALLATION_UND_ABNAHME.md
d51225e4748ee07fd608c343fa4119f04b5fcdaa946fd1c9ff9d252b0226b788 03_IST_UND_LUECKENANALYSE.md
962fd825225026de0ce4820a3412ea808f6458280e5d7ec6f20126d2e7817837 04_ABNAHMEBERICHT.md
db19a5a2dddf67182e011c6f5df5cc587345f8ff94bc0e20f79886137427a433 05_ROADMAP.md
f344f75df655bc133e6c4abb2d215b2234fb22a4bb155c217317c36ee4f0f8fb vendoo/.dockerignore
e5cc1e85c80485ceda76fd6c69330e085ccc7bc1248be810fe4243712cf39118 vendoo/.env.example
58e3f4b76cc9398f32dcd5481b2080e7e5ba322aca04b8b8374446299c5d7dd6 vendoo/.github/CODEOWNERS
5bd335eb750d084ca12b6a3b3f35d0cd7bc454ba24ed280187c66acf75eaf396 vendoo/.github/dependabot.yml
f65684e98b01d0e0b6bfe1284b5de3354559e4cd51e634fe9e9e2e5473b890e5 vendoo/.github/pull_request_template.md
6641ae3ef2b49dbf2d0f76fe1d0c8a76554fb154a0c82738c49848f466cc776b vendoo/.github/workflows/ci.yml
e3efad6c06973cb58958c9d4f8cdb8adec61907acb82804c06b6b6a0aaa1d160 vendoo/.github/workflows/release.yml
9e7decb6c419fc032644ad361043e69770104ea5904bfcce4942f9416787d975 vendoo/.gitignore
9bfa732952ad571d06527b32d96d79133fc23fa607df00de440b2802f543608c vendoo/.npmrc
3ae3049aaf372d61f1d39f53c97f697128b352aff1726c6e3b99feb86223a264 vendoo/CHANGELOG.md
61823fc9fdc036170cce6edeecbb612b442d1c65fc9f7a7eaba47e5016316ee5 vendoo/CLAUDE.md
2e0077cd6dd83d3a07fcef25b7e37ab5fc056dbe1ca034b33d55135234045882 vendoo/Dockerfile
3a72c2ba86fca6655af49a47e853a335532586dbf5ea620d909570ec7d76cb02 vendoo/FEATURES.md
118ef8630141ca6402fce456687363c020f9444e496912b8cc6c7553e0975279 vendoo/FILE_CHECKSUMS_SHA256.txt
7f78a0d512de717ba76c9a5e3e1bd2e52db9edf146e8eeb7297458fde5d92afa vendoo/GitHub-Deploy-Assistent.bat
302ab1609d08b3059ba6563b676c64f0709651f2e3c531857bfca3840c535a79 vendoo/MockupDesign/AdminDashboard.png
49f7625a1299a16576feabfd7824ec3511391bd9b7c53a1fba9232da7e8bd6c6 vendoo/MockupDesign/ChatGPT Image 7. Juli 2026, 10_05_19 (1).png
7b8cc9c5db8718b0b653ec6aa9d2a8bfa1bba03810248c3ba17745b6f15cc412 vendoo/MockupDesign/Dashboard.png
4e3e797ed5d3ed0b60d00d8e567fbe51543c08578b858ef71e77b274ae449fd0 vendoo/MockupDesign/Einstellungen.png
c78fd6f673c0e59789ea313396b12c2f21f75a2ee6c7ad2de81a6b89f6d90588 vendoo/MockupDesign/ExtensionDesignMockup.png
ed20bc04cab8e85245a855810a61b736a682f972eb85e23340edc9b558851a93 vendoo/MockupDesign/Heute StudioFlow.png
1ad88f45f377ab9b3f35f96a0ceaaa7f75cb0a996e83370d76c54f527392a08d vendoo/MockupDesign/IconLogoMockup.png
0e8b4a31d075f1f83ea62b5eeeb53e89859e395a696deb43155932a23e7cef86 vendoo/MockupDesign/Lager.png
b1c62e118d9be316274e966c558cdcccdd41afb3a9f05a60ec1e4a3433d2ca0c vendoo/MockupDesign/Listings.png
a52983b9ea2bf920d115485d10bc30226da88bc5cba8b00bebf801b21c096346 vendoo/MockupDesign/Publish.png
8c8bf278d0c6725e1dbb97b3c3d0c36a9bfc0753c3c86433fdc294bec70dbc0e vendoo/MockupDesign/Startseite.png
62f14221b1d71c9e631efdadd221397ff657adae4b737df52c8bff1610b90999 vendoo/MockupDesign/Vorlagen.png
13ab5b29d5bb22a7c48e7a782a901681de0a5ea314fb243d863c063f6a39d3bb vendoo/README.md
3cc4cbb3f67a7cff7fc1892dd1b9d695dd1b6ed1596ce454b2edbd11ecf76faf vendoo/SECURITY.md
2851c914a1b50a036cb265ddd32e5545cc7e8e34ba9d682445926acc23eb8f28 vendoo/THIRD_PARTY_NOTICES.md
4c424ef64a09639953388bd2e749d45e9a0d3d533c8b6fce547292237a0a48f9 vendoo/app/architecture-boundaries.json
a6bdb9b6fdc97a0b2bbc052bd242a9885a75bcc46ee4f0414d8b7e215b6940de vendoo/app/contracts/module.schema.json
918cddaee5056cadddcff39d86744cf68ab409fbff46aa54b6b465b72b199c01 vendoo/app/core/security/secret-contract.mjs
7f38b3ac792e61e030c9f69355e2378f8f61e8e61c7b29c82cd0fa7ec930cfec vendoo/app/core/themes/theme-contract.mjs
d84a573699e413e0a0803459e0d05c5c4e6e35d3499eb634f95302d151e75c4b vendoo/app/kernel/errors.mjs
a34333cbc784d39b39a8071a437972c6175c551104dc2d82fc4c0e0506b18259 vendoo/app/kernel/event-bus.mjs
0e8f691f96e1ef0a7a86d32cae7b7e1db04325fe94a32b8c1f484a5b6950f3b4 vendoo/app/kernel/feature-flags.mjs
e2e0b74fa04efa787c0494c0d4b755b9445c6f38dc8d9cd7ec206683b0fb1da8 vendoo/app/kernel/input-schema.mjs
a0223a00691908862aaf1fd9383b6d86d67f26325c509280b8c2daa5cfcee28e vendoo/app/kernel/lifecycle.mjs
ba1f4f799a508ff113738cce7ac9f5af27739cb60d7f04d7a6c5878de3c5b7f4 vendoo/app/kernel/module-contract.mjs
1baa99ffd80fffcfed69f21a5db8911500f35c0bd9df23cd02a7fb3b563266df vendoo/app/kernel/module-registry.mjs
99931e7923b879bd68ceea3cb400ad041f3353e5c341e8a5643fe77f662ac213 vendoo/app/kernel/platform-kernel.mjs
7944f68d995a5d70273f8a985973f668fc62a414d85636d92f3774e34d39a37f vendoo/app/kernel/policy-engine.mjs
7547f4cae608feed54669fe94cc787ba2a06baad3c9c969d072fd11cca34288c vendoo/app/kernel/route-registry.mjs
0bb099111f7cf49780389d0b078083756a448b663661ee22475d84d38a5f9719 vendoo/app/modules/ai/module.json
83ad66e0eba88246d292c96fb1ec02b9c59ed15614bbbf4a4a989787fe51e2d3 vendoo/app/modules/auth/module.json
dd28d6157d97aa812894a2db96c02f78200565e5adaf5913f92b1fcde759a705 vendoo/app/modules/catalog.mjs
083db2c78089db389e51e743078c847f1067f3d1a39081080c601d31556f15fd vendoo/app/modules/flux-studio/module.json
82b31b548c603cdc4e21b50707fd3d21114b85ef1f61db607c881f9ac1809132 vendoo/app/modules/listings/module.json
6453b41f4074b37c7f7a2c30aa8a0eba8c4233f8d474251919094ed0c15fe38d vendoo/app/modules/media/module.json
9723a9b12a9b472b2ed8c4635cdce663b2f0f65643d8ae0b6219715d853f740d vendoo/app/modules/operations/module.json
b71c0f607bbba70b4485fcce883a7d2ab4a533a6dc203eb7de616aa4d8bae435 vendoo/app/modules/publishing/module.json
61aa66129d18e2c5e6c2e7319de836a4713fde1ddcc31c6a5ca56c22d22d9b48 vendoo/app/modules/quality/module.json
747febc12aec7d81ccfdf6e9ea7158655ef5fdc536c519ce447de329314612a8 vendoo/app/modules/security/index.mjs
700be862cd70be6947919c1e1f0e25e7e88c313b1fcdddc104d54d88a74edbb2 vendoo/app/modules/security/module.json
452a5262c418b393bdd8754fe90f9ea14edf61338f8dcfd6438f0852920f608c vendoo/app/modules/system/module.json
92d968c993ee5a2afc14df557b7cba552cae9a41722989007eb0b784514333ff vendoo/app/modules/themes/index.mjs
1e062db871f9bf13b487c972f6cd4dd9cfe1b3046cd9b53ed43e0a0babc9d285 vendoo/app/modules/themes/migrations/001_theme_profiles.sql
2af572390890e4d793aea9c1356c835917655c225a7848325d5a7c5ae3c08a09 vendoo/app/modules/themes/module.json
3c3dc5974976672cd0e9141867a8a1d78a0dfaa54582bafb8f360bea571bf11a vendoo/app/modules/themes/repository.mjs
4e2c348a184384739408894f26b02c56c6bfd4dd531eebb9c67d2fb7fbad3009 vendoo/app/modules/themes/service.mjs
11b4a1bc94b68998a3a2a8bec766bc56c7ff829939d914b0ce896f963feb10ed vendoo/app/modules/users/module.json
c197ce417fbce6dab1d8ee157b0a105a099dd2021ece4dac3891d0b2022a0d58 vendoo/bootstrap.mjs
4a3273ec603224a70ceb81c0d5ed6617c3ba2d3111342b4e646a79752f4b3f87 vendoo/compose.bind-mounts.example.yaml
66d2e8a35289748f472d3ca2d703fe878f616b22ba30b1344251f78af07e3ecf vendoo/compose.vps.yaml
69b9d6721198f5a93840ee4fb6ece45caf2898f036c3f9bba9aa05f0f4199964 vendoo/compose.yaml
6323f984f1e04ab135356a14ec151941638041f6b305ed68772d5e1812972075 vendoo/db/schema.sql
49690c4e4c8e84de8eb40ffe79823493b7be20fe46fa2ad9e6544f7f0afbfd2c vendoo/deploy/Caddyfile
cc794bca282d79a27d860d0bfef4641769f4e9f31172778a1d9d8205558d948e vendoo/docs/ABNAHMEBERICHT_1_32_0.md
de0d86f806a70195050613f5b56f6c4da1ee2eff02a9a991b6aacee229c46ca5 vendoo/docs/ABNAHMEBERICHT_1_33_0.md
947745174897470de0bebf4f7c2b29a0c0ef3f1a762f277374c2614d9e3dec4f vendoo/docs/ABNAHMEBERICHT_1_34_0.md
26c87fa38f804749a9363812127dc33ef69e201e4ef9b59206f6fe6e15c845b0 vendoo/docs/ABNAHMEBERICHT_1_34_1.md
f792d366c13c5a4a9b4e8d4054e26190d9c327a7a770005d74bbe2b31bb84ab3 vendoo/docs/ABNAHMEBERICHT_1_34_2.md
bc638fd21222ada7b15e40adff80a318aebec58139978109cbfd30040815a8d4 vendoo/docs/ABNAHMEBERICHT_1_34_3.md
c0ae5c4176ba6f7510be047d4feaf383cd646152131003ebccc6bfbf8c8056f5 vendoo/docs/ABNAHMEBERICHT_1_35_0.md
c050c8e11f2bdb0a742851423dcff864bafba9cc839c52b2f8d48b75f7b18633 vendoo/docs/ABNAHMEBERICHT_1_36_0.md
1f3e96ba13844a3f1cefecca99b3d6313aebf86faae914897db0404ea031c491 vendoo/docs/ABNAHMEBERICHT_1_37_0.md
67a1be91b0c2d2797716f785f2f770c881cf88d7fd617722468df8d949d0638a vendoo/docs/AUDIT_1_31_0_IST_UND_LUECKENANALYSE.md
2acba8fcc5da42e5a808925a86628bc0c6fc817ddb082b0ead3857c6a43460f1 vendoo/docs/BRANDING.md
f23c643236c84b0e3715620598f358065748b6d090229003e23df8ad9320b54e vendoo/docs/FULL_LISTING_EDITOR_2026.md
ba9a9b93622fadc399cd9067d80b4ea339193eb19825106264a3b86b7128d107 vendoo/docs/GENERATOR_STUDIO_2026.md
54f45ae5c2f12b6314b3f1bc3e59e753c64ca7cfe39644725d765e9f02f637ef vendoo/docs/GITHUB_DEPLOYMENT_1_34_0.md
5a25e952d7d79b562bc19c990451830ea2ac3e730c9af399425ea18ffb8fd61d vendoo/docs/GITHUB_IMPORT_STATUS.md
65d19c1576f4a6011008a7e447a3530222517752fb59ebc5bbb506b791e32605 vendoo/docs/HOTFIX_1_23_1_EDITOR_CACHE_VINTED_FIELDS.md
c9c8f934a0c4192dae29df913588188aab1321364d1c46b9c66da5c754e9df41 vendoo/docs/HOTFIX_1_23_2_FLUX_EDITOR_JOB_COLLAPSE.md
2306ff399000c07a9d7e260a58d92c748fa3219922a4dda25f6b2121a1ad2dbc vendoo/docs/HOTFIX_STUDIO_FLOW_DETAIL.md
0584257245a29de62a6374eb8b114bd19fc6a36306ed990d820ed2062514d6a6 vendoo/docs/INSTALLATION_1_32_0_WINDOWS_DOCKER_NAS.md
7c1afdefd1e3a75a5d6b49aedae80e266bab4e91cbfc657fb862ddfd737dc792 vendoo/docs/INSTALLATION_1_33_0_MULTIPLATFORM.md
1475e484cccb0db67e02abbb05f8b8e676c85536ec4f5bda7dd99d4563fbc049 vendoo/docs/INSTALLATION_1_34_0_ZERO_EDIT.md
1df2aed413865c03e541e66249c1df3eed6d3c3aea9f0ffdeaee40453665df14 vendoo/docs/LISTINGS_UI_2026.md
4f74fef6877126d2579356b9731955e29f05ea8b55b59abb91569e47730a1c3f vendoo/docs/PUBLISH_CENTER_2026.md
bae236366d6d2cb0139e4dbf8baf099599bbff27aacc9eeeba20fdff644f5fb0 vendoo/docs/RELEASE_1_24_0_RESPONSIVE_MEDIA_FLUX_ARCHIVE.md
5223408e51f35ba5f6ce86155544311dd13f60522a6d482f372d64788ab466ac vendoo/docs/RELEASE_1_24_0_VERIFICATION.json
b66524ffd19976f650c6b26b299898b182355950f545c131de16c89fcffe0ebe vendoo/docs/RELEASE_1_25_0_RESPONSIVE_GALLERY_SMARTCOPY_PROMPTLAB.md
1c5ebf1a496c9571fe9d941793371f9f0be89d85a587c8fa9532f9b25bba92bc vendoo/docs/RELEASE_1_25_0_VERIFICATION.json
1eef86e13d9429701e9d60894f36fe0eba82c974565b1a6687ed157ca6da680e vendoo/docs/RELEASE_1_25_1_ADAPTIVE_GALLERY.md
14475ae4169f4bde4a5b7ae5512867f972ede69dcb621d7cc6a208d4fdc6a331 vendoo/docs/RELEASE_1_25_1_VERIFICATION.json
f02b80194f434dd3d82b5c4c111e8cae65f1f053a267cec2793a1ff551daff9a vendoo/docs/RELEASE_1_26_0_ARTIKEL_EXTENSIONS_PUBLISH_GALLERY.md
570522a6513134227122da1b5f2f56a421c62d3b0b5adba703872e9026fa2b58 vendoo/docs/RELEASE_1_26_0_VERIFICATION.json
4cfc47f35765259cbd6a841f51a85fa86600991d1ca545b10756f15b6d332f7f vendoo/docs/RELEASE_1_26_1_STABILITY_GATE.md
9646b913994b1bf8ce03eab57e7a6a87061540e44fdde63ad5b7eee93ca9f475 vendoo/docs/RELEASE_1_26_1_VERIFICATION.json
7c6c3a2e4ce478f47e540a34a3505dbbe11b8f2175d0b274bec7643457997140 vendoo/docs/RELEASE_1_30_0_OPERATIONS_CENTER.md
6f9c206869ba94c461b1d9f8e40847792b8891bb27809a0c6fa3d1d68a4e8598 vendoo/docs/RELEASE_1_30_0_VERIFICATION.json
5da62e06d768ce832d18fb3ecb3ccca2f051a6218d2d3cb492d1e5aebbcccb52 vendoo/docs/RELEASE_1_31_0_MULTIUSER_SECURITY.md
6288a31dfa61f71d13f79d40ab64bb7ca475de07ada154c002cd4b0d44a284dc vendoo/docs/RELEASE_1_31_0_VERIFICATION.json
4ee88ff8c3c655cb31bc18192a37ffdd0eedf8e26039b252094d5ce169c1883c vendoo/docs/RELEASE_1_32_0_DOCKER_NAS_PRODUCTION.md
628d4d1a6c7d837a0c8c22958253193642ddfeaab5f425f418f9f32b46e84340 vendoo/docs/RELEASE_1_32_0_VERIFICATION.json
624919ea60969079f767068771800dbc04ea7a87eb1a53d7f0497447492c25cb vendoo/docs/RELEASE_1_33_0_MULTIPLATFORM_DEPLOYMENT_FLUX_ADMIN.md
3f9ae39792bec600ddd534284ae62cb2b4f9db01fb54c09cee8ae161551caa2a vendoo/docs/RELEASE_1_34_0_GITHUB_ZERO_EDIT.md
c724b699894d5ec3c050af0253c6de0c645a789219a344ad7ffe31e330d9921b vendoo/docs/RELEASE_1_34_0_VERIFICATION.json
7caa9e7b1e51af362332e9c50165b60c54c9219c7384c8313d3735c387df1c01 vendoo/docs/RELEASE_1_34_1_GIT_SAFETY_WINDOWS_HOTFIX.md
ac834ee57ab6bd8fe3dd0238837193e66e01d7e78590a289347b002591da3fb4 vendoo/docs/RELEASE_1_34_1_VERIFICATION.json
51057d17e2636ef1bdfc6751dfad29ebd34fbe7f41b870f8f2f756a5c97d1c4a vendoo/docs/RELEASE_1_34_2_GIT_SAFETY_DIAGNOSTICS_STAGING_FILTER.md
4c2c141ffc85b1d7517672abf2b28bb19fe4769505c0eb4d37e22bae06826cb3 vendoo/docs/RELEASE_1_34_2_VERIFICATION.json
d55eaec79e10800a930fa030367ffa34037755e5757bc532e72d25711c5ca09a vendoo/docs/RELEASE_1_34_3_UPDATE_ARCHIVE_EXCLUSION.md
4bb731af51e786a4827ec48bc7c4d4843c287456aedc09d8b74aa0eed3c0ec16 vendoo/docs/RELEASE_1_34_3_VERIFICATION.json
e7bb3bb950e3c5303746f43139ca8f7c985d2d73896b44f5b707dd46a9152529 vendoo/docs/RELEASE_1_35_0_PLATFORM_KERNEL.md
33eb9f0059a2ddc4b4debe5bf733720f2a5bb22f2710bab0a0cc9ac1b898ff11 vendoo/docs/RELEASE_1_35_0_VERIFICATION.json
5a9fcfa0ea6e9c5c13f6d943e1de4d31c21e21fcff9186e8a714d7a16ed1c18f vendoo/docs/RELEASE_1_36_0_SECURE_THEME_MANAGER.md
2dfe705857424865f101e861f4e633c8a7fb3c0e8dab874cb6620fd09b1ca902 vendoo/docs/RELEASE_1_36_0_VERIFICATION.json
527806c00fb51334457726a9a7e9f6fc13f4dacd985fa2d2b97d5eb21c543853 vendoo/docs/RELEASE_1_37_0_SECURITY_SECRETS_OBSERVABILITY.md
fe5756f788b2ab131f0832504d90d46d1ed744bfe470fd040803985234afa3cf vendoo/docs/SLICE_02_ACCEPTANCE.md
05614ecf41becc399acfa6a3b2f681f37a8c80f5ce0130b98c578b2c8c60713c vendoo/docs/SLICE_05_ACCEPTANCE.md
0838bcc6464a6beff39f0b4b056e513c1a390193521d9a8fc5d440d38034e9d0 vendoo/docs/SLICE_06_ACCEPTANCE.md
ae0f7c6f6e614ec77e362db1076288596ec48d11b78f33f26908fbc40ae5dd18 vendoo/docs/SLICE_07_EXTENSIONS_RESPONSIVE_MOBILE.md
b561983736639a08146d3642b718651907853d589ee32e5f421fc090f2c75a20 vendoo/docs/SLICE_08_EXTENSION_AUTOFILL_UX.md
c5bf7a0c9f787f100e422d0deb27bffc2c8c86b0e7c1ce1f35d2de8d7d8ea774 vendoo/docs/SLICE_11_DASHBOARD_RESPONSIVE_HOTFIX.md
876675bc3015838f568a6970ef6c01c9fcafe1d8d138c4379bc0f2ee1fd7445b vendoo/docs/SLICE_22_1_SETUP_AUTO_RECOVERY.md
223f50d05096b3bfa3ac3a9f0880a2055fc2029b7d70fabd086612c3348cb34a vendoo/docs/SLICE_22_2_DOWNLOAD_RECOVERY.md
95e1d560378120d7ccb0f363720ba832505631aa65616abd4df01baba5ecc269 vendoo/docs/SLICE_22_3_POWERSHELL_51_PARSER_FIX.md
88f5a2d021874764b6a7f56c690a1e2112155b83cdf0d4d964b2c6e00ca756de vendoo/docs/SLICE_22_3_SHA256.json
791a5d30f0d6ff9664722a2d00dff0db0bbdf2207e83ab391a40d6c4ab913bba vendoo/docs/SLICE_22_4_SHA256.json
d14c938c6c9397290f654406d4b995b63db0f22586e78fc97fb5fef575748807 vendoo/docs/SLICE_22_4_UTF8_BOM_FIX.md
f00c325ec3c879b47908dd5410cc943febb923200e9b9bd7d18197b1570a26fe vendoo/docs/SLICE_22_4_VERIFICATION.json
e140f3ee3298b3894126e37900b04ff1073ed400e6414e35897815b3f674d93e vendoo/docs/SLICE_23_FLUX_REFERENCE_PROGRESS_SETTINGS.md
b4b01b9f3751940d184d6fff269108798c7ec62ca7796b923cf82abbc142ff3b vendoo/docs/SLICE_23_VERIFICATION.json
05e3fcf5aa9a0d8d53175a3d24c5feb36e55f73edfeadf05384e87a5de73353a vendoo/docs/SLICE_28_1_FLUX_RUNTIME_HEALTHCHECK.md
43d867bb8b455f7450e5146648b28c759e50ebab45855d75a36dbc9f91d3f654 vendoo/docs/SLICE_28_FLUX_STUDIO_VTO_CLEANUP.md
0bdbeed4b57767427afbebeddc30ea58a211f851663939d6301af38820cf098f vendoo/docs/SLICE_28_VERIFICATION.json
1e20fd1abea3ce61f7f9cc88c6e8e4ddb0fe3513c5600e41b8f7c3f8d38e3ae9 vendoo/docs/SLICE_29_FLUX_QUALITY_SETTINGS_TABS.md
1df7305e6a43212a582d5f83630e0ba04fbdd3da0d673d9dcb8f1c5f7ca37731 vendoo/docs/SLICE_29_VERIFICATION.json
07d1ad0c19567cbdb05623567816f1506197a31e86fbcd1742f4ffa300335ae4 vendoo/docs/SLICE_30_FLUX_STUDIO_PRO.md
008237388c4816d3cd67f3f0abfd0512f4ebf2dce75ab6790de41b0481ae1d97 vendoo/docs/SLICE_30_VERIFICATION.json
db1674505e2ca7eb36c8752ea9b2d6fe2f2c12a5e6a1584e2722e20445b05e34 vendoo/docs/SLICE_31_ADVANCED_IMAGE_EDITOR.md
3133a06e68cd98e615797665956f1bc401c0427045298b46c48ca590be3ef9da vendoo/docs/SLICE_31_VERIFICATION.json
d425fc1724ac55853bf3433348486de8f8aab111f53fefee3c532beb1deb82af vendoo/docs/SLICE_32_BATCH_IMAGE_FACTORY.md
0a8917412d000168956f7ac55e60ab79b54a8834deef0386a681bb8f920514cd vendoo/docs/SLICE_32_VERIFICATION.json
25ff8492360d473e99c75c308be5f75cf84e0c11574d42aa6553d44f8bb35582 vendoo/docs/SLICE_33_ARTICLE_QUALITY_CENTER.md
1d5411f69c62222d3155f0e89f2b4b5a3effe317ea1e59347efa7730a8e1b0e9 vendoo/docs/SLICE_33_VERIFICATION.json
1161decfabd73c40ff1d2ffbc7d1b9b5168a8fb5fa392187c1b431e9a7f3a78f vendoo/docs/SLICE_34_PUBLISHING_HARDENING.md
aa7ebc90470071566749c61b0dece4169f87666dcca4b88922f7fbafcfdd5a84 vendoo/docs/SLICE_34_VERIFICATION.json
4b66a14b4515e38477f10325ab9d03d9782ad0d426845aefe2d508986ed2cd81 vendoo/docs/UI_FOUNDATION_2026.md
5e655fcf3bb1182f8850b4104b56697ea952b01d2698af6d3d40b05e338b3506 vendoo/docs/UI_UX_FIXES_SLICE_03.md
e5f065ba8d516a5ebd47e7e6859d0aab40ef69797413e358d969ef27c454fcdd vendoo/docs/architecture/DESIGN_SYSTEM_1_35_0.md
cc0edf92756a51414563b4407dedb21d1e3b36682f4bfbbc334aeb33a22ae1b4 vendoo/docs/architecture/MIGRATION_ROADMAP_1_35_0.md
eb47b055dd336e8360ec7c4712dee4ae37f109f3820e3f185969e2327d790cf8 vendoo/docs/architecture/MODULE_SYSTEM_1_35_0.md
d7773faac0e93510a5a51c91de997df03547b51f3124267dcf137d4e99299562 vendoo/docs/architecture/SECURITY_ARCHITECTURE_1_35_0.md
58cd43938b06e29520b92516a1e816d17d2c08d4847b99c1ee700b2185f46f20 vendoo/docs/architecture/SECURITY_FOUNDATION_1_37_0.md
771c4771c4d7335750c5a2d976c765b4ed66ed936d8550d7af69de14a16705bb vendoo/docs/architecture/THEME_MANAGER_1_36_0.md
cc77a92ca268d3c444c6113a9cfaa38d3c805a579f6b1b21b7dd43a6ada58551 vendoo/docs/superpowers/specs/2026-07-06-autolister-features-design.md
c7db96df5fed3c8336062204322d62b4870f5c8ab1d30ea48cc6e7e38ed3513b vendoo/extension/README.txt
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e vendoo/extension/background.js
b86f00c7afa1dc921dd66f5cfea8c817eebc8876b9daca6a55dfd03680156c79 vendoo/extension/content.css
8ee8d1a94bbf83e5d09aee3c7d8c4ea5f216b2a51e73b6dbc74f7e6b99017a1c vendoo/extension/content.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf vendoo/extension/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b vendoo/extension/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 vendoo/extension/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 vendoo/extension/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 vendoo/extension/icon.svg
c2fdc0530c71ef400fe9d52aed914f65d331b0d89dfae7ef1d156d54d1a22a6b vendoo/extension/manifest.json
e61fd8e1264995fd633bd76e71329813dd02f361286329832a18dfd5a8bdd372 vendoo/extension/popup.css
bdf5b794473cae818789cf95a28a9c9a9d50f81529d72fdf45a536247a783922 vendoo/extension/popup.html
d7893cfdd686d4a6a1bea333468d4ba72cfff0e7166687181a2d37ba1faf3332 vendoo/extension/popup.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 vendoo/extension/vinted-categories.js
48b5f9f4ecc1c1c42f37321e9bb2fc857c646b9c16c34520fc7d4ca59a1036ac vendoo/extensions/README.md
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e vendoo/extensions/background.js
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e vendoo/extensions/chrome/background.js
c5a0ca59a8858e9bd484d1e5fb7a2aca72db092fb062674f531bb76f5a0c952e vendoo/extensions/chrome/content.css
22bd64723d279a6229bccba2a4cec56f1ae83f4cd5628bd1a1841930b0f442f6 vendoo/extensions/chrome/content.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf vendoo/extensions/chrome/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b vendoo/extensions/chrome/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 vendoo/extensions/chrome/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 vendoo/extensions/chrome/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 vendoo/extensions/chrome/icon.svg
c2fdc0530c71ef400fe9d52aed914f65d331b0d89dfae7ef1d156d54d1a22a6b vendoo/extensions/chrome/manifest.json
e3a3863b58a571a0f0180bdd333f9389b918415b4ea96b70f3ab6d4105d95c50 vendoo/extensions/chrome/popup.css
559dc70841ebb186ff96f9f2ba32ef26a3a7f8edd08363f09c0d7163049eae5a vendoo/extensions/chrome/popup.html
2bf2d5ccf02622cf1d62fd553d21c0ef1b744616742e7962ac302c10d37426e2 vendoo/extensions/chrome/popup.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 vendoo/extensions/chrome/vinted-categories.js
c5a0ca59a8858e9bd484d1e5fb7a2aca72db092fb062674f531bb76f5a0c952e vendoo/extensions/content.css
22bd64723d279a6229bccba2a4cec56f1ae83f4cd5628bd1a1841930b0f442f6 vendoo/extensions/content.js
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e vendoo/extensions/edge/background.js
c5a0ca59a8858e9bd484d1e5fb7a2aca72db092fb062674f531bb76f5a0c952e vendoo/extensions/edge/content.css
22bd64723d279a6229bccba2a4cec56f1ae83f4cd5628bd1a1841930b0f442f6 vendoo/extensions/edge/content.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf vendoo/extensions/edge/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b vendoo/extensions/edge/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 vendoo/extensions/edge/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 vendoo/extensions/edge/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 vendoo/extensions/edge/icon.svg
c2fdc0530c71ef400fe9d52aed914f65d331b0d89dfae7ef1d156d54d1a22a6b vendoo/extensions/edge/manifest.json
e3a3863b58a571a0f0180bdd333f9389b918415b4ea96b70f3ab6d4105d95c50 vendoo/extensions/edge/popup.css
559dc70841ebb186ff96f9f2ba32ef26a3a7f8edd08363f09c0d7163049eae5a vendoo/extensions/edge/popup.html
2bf2d5ccf02622cf1d62fd553d21c0ef1b744616742e7962ac302c10d37426e2 vendoo/extensions/edge/popup.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 vendoo/extensions/edge/vinted-categories.js
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e vendoo/extensions/firefox/background.js
c5a0ca59a8858e9bd484d1e5fb7a2aca72db092fb062674f531bb76f5a0c952e vendoo/extensions/firefox/content.css
22bd64723d279a6229bccba2a4cec56f1ae83f4cd5628bd1a1841930b0f442f6 vendoo/extensions/firefox/content.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf vendoo/extensions/firefox/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b vendoo/extensions/firefox/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 vendoo/extensions/firefox/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 vendoo/extensions/firefox/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 vendoo/extensions/firefox/icon.svg
1954ca9f34b3afe109935173f685482f06bb685a9b8f0d4c344f0c6133ccfaaf vendoo/extensions/firefox/manifest.json
e3a3863b58a571a0f0180bdd333f9389b918415b4ea96b70f3ab6d4105d95c50 vendoo/extensions/firefox/popup.css
559dc70841ebb186ff96f9f2ba32ef26a3a7f8edd08363f09c0d7163049eae5a vendoo/extensions/firefox/popup.html
2bf2d5ccf02622cf1d62fd553d21c0ef1b744616742e7962ac302c10d37426e2 vendoo/extensions/firefox/popup.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 vendoo/extensions/firefox/vinted-categories.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf vendoo/extensions/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b vendoo/extensions/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 vendoo/extensions/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 vendoo/extensions/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 vendoo/extensions/icon.svg
c2fdc0530c71ef400fe9d52aed914f65d331b0d89dfae7ef1d156d54d1a22a6b vendoo/extensions/manifest.chromium.json
1954ca9f34b3afe109935173f685482f06bb685a9b8f0d4c344f0c6133ccfaaf vendoo/extensions/manifest.firefox.json
e4ea31f91a4c8df18901bfc77fc351a8808d19d690243b80bc4faa140e18f851 vendoo/extensions/packages/vendoo-link-chrome-1.9.0.zip
e4ea31f91a4c8df18901bfc77fc351a8808d19d690243b80bc4faa140e18f851 vendoo/extensions/packages/vendoo-link-edge-1.9.0.zip
74c219587cf0f827a1a1e2b8adacac55477be717fd4ae80e2ae027a9ffb0744d vendoo/extensions/packages/vendoo-link-firefox-1.9.0.zip
9e828844f41154c87ccfc5d8f3a19476396e2782fbd0f956465b42fb508cb098 vendoo/extensions/packages/vendoo-link-safari-1.9.0.zip
e3a3863b58a571a0f0180bdd333f9389b918415b4ea96b70f3ab6d4105d95c50 vendoo/extensions/popup.css
559dc70841ebb186ff96f9f2ba32ef26a3a7f8edd08363f09c0d7163049eae5a vendoo/extensions/popup.html
2bf2d5ccf02622cf1d62fd553d21c0ef1b744616742e7962ac302c10d37426e2 vendoo/extensions/popup.js
afd76deccd8bcf26d39f8c86deb1de578873ddd8b09ac18eebacae33169bb420 vendoo/extensions/safari/README_SAFARI.md
0b2a03d06faae7aaebeee8ec9fe1864422c8651f17ae90b185fd31474ac5eeb0 vendoo/extensions/safari/build-safari-extension.command
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e vendoo/extensions/safari/web-extension/background.js
c5a0ca59a8858e9bd484d1e5fb7a2aca72db092fb062674f531bb76f5a0c952e vendoo/extensions/safari/web-extension/content.css
22bd64723d279a6229bccba2a4cec56f1ae83f4cd5628bd1a1841930b0f442f6 vendoo/extensions/safari/web-extension/content.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf vendoo/extensions/safari/web-extension/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b vendoo/extensions/safari/web-extension/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 vendoo/extensions/safari/web-extension/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 vendoo/extensions/safari/web-extension/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 vendoo/extensions/safari/web-extension/icon.svg
772f1e2e33f4d6d882fa0af663e315fd3b8208141227bb5beb9baaf1f4e08397 vendoo/extensions/safari/web-extension/manifest.json
e3a3863b58a571a0f0180bdd333f9389b918415b4ea96b70f3ab6d4105d95c50 vendoo/extensions/safari/web-extension/popup.css
559dc70841ebb186ff96f9f2ba32ef26a3a7f8edd08363f09c0d7163049eae5a vendoo/extensions/safari/web-extension/popup.html
2bf2d5ccf02622cf1d62fd553d21c0ef1b744616742e7962ac302c10d37426e2 vendoo/extensions/safari/web-extension/popup.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 vendoo/extensions/safari/web-extension/vinted-categories.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 vendoo/extensions/vinted-categories.js
9a5bfcafdce53130d7bc36695090a8f87096b4ead9dd5ccc3d46d1d80c07a0fa vendoo/lib/ai-claude.mjs
b53b7a8dea3bd46bee9c32e2ea840d618b5cb31cceba49937c057ec615fb87b5 vendoo/lib/ai-flux-prompt-jobs.mjs
347778ce521a1919ec0679918171dc625d7f04d6dec26c8a4700e702bc78de67 vendoo/lib/ai-local-images.mjs
aeb5103c0179232b9954b7854be8099cf4bb0f3ef1ee908eb5e4faf6a8f1205f vendoo/lib/ai-local.mjs
cad43695655fc1c805815d9d694f23bd41124c1b78bb6493e7fea8893c464320 vendoo/lib/ai-model-jobs.mjs
9f474f665d6d610fe00d9e707e85314a854abb906e31db2bb9a3a7c76785ff4f vendoo/lib/ai-model-photos.mjs
3fb484456b9e6374f14b53a2276eea8533642b7c9073bb73a1bb0dbed7048bbd vendoo/lib/ai-openai.mjs
581c10b8346d0aa10169ed23ed49c038951ecd5cac014722c1080bbd5aec1c5b vendoo/lib/ai-openrouter.mjs
271696d7cbef3581b667a8ce3b07d0b17b1e8b467fbede4d8aa512ecc5225515 vendoo/lib/ai-router.mjs
76a2f1fdf60053739d82962264219060807022dfc9a2b3a644946fddff02a8d9 vendoo/lib/archive.mjs
ee6aa662a1875f9df8da1000804a6061f1a0f52c7a266df3d515cab4d410465b vendoo/lib/auth.mjs
3e2b75c0758703e590233cbcc9b589e3177134accecf5ed921791891cbfc8522 vendoo/lib/categories.mjs
86793fb57a1dad32f4d93e34c27ffe9e77a95785dd30b2b55ffb67d0ad5e14fb vendoo/lib/config-store.mjs
8c203e70e9ab07b996d4a53031892bbf37b10efd024f9e0013266cf2af0244a4 vendoo/lib/db.mjs
54722d3f76ad9ee4fbe731d3a65c2a03d343eb82d98f8ea5a5996b1bec24d57f vendoo/lib/ebay-api.mjs
524f1b48d467998da819f0b947f2551ad45784e588eb442304c5f6e925dffaee vendoo/lib/etsy-api.mjs
5b2c566ff14fa502ba2cd4d4c918fe238a8e93c3283d521144093a897f9d8018 vendoo/lib/fees.mjs
7dcb2fb5606140afb7a019094d20ef88e9b4e2c70041f77b06d67d8992fd25ce vendoo/lib/html-templates.mjs
844f0f8bc1de849bacc8df5d57006d5fc1100c706acc1140939a981dfdf2df4b vendoo/lib/image-batch-jobs.mjs
5ca5fc65a7de7c27243646d291dc42c0b5267a47705a09b306cd2c2eae2a77c8 vendoo/lib/image-editor.mjs
5e7aa66faddd3d19bc6ebb9ddc13abfc4ab4f17d8c51bb39b2c4e0279385d788 vendoo/lib/images.mjs
606f4cb1013c711d971dd201ab06df84ecb128bf5d5277095ce2e2ea56029e45 vendoo/lib/mailer.mjs
ad53b2b39f894a685f79e723b3f2b987fc9d9a3b75d39d0059ad225bc36c08cf vendoo/lib/operations-center.mjs
78d30585aac7dc663e803a19927c89ab02414c0495d81df503e28f7bae58701a vendoo/lib/publishing-jobs.mjs
3a728417dd668d60fd1526ec738cb9b302f86c01d62b2227f12b2e44b7d389c7 vendoo/lib/quality-center.mjs
faa5d84ca6b26d1602e53a402de74a5c9e3f9ef9a72233159101f2b0bb0e499f vendoo/lib/runtime-paths.mjs
d3d862ab32fd276ecffb54c0307976ca680135d92f24d024c95d365a50257643 vendoo/lib/secret-store.mjs
cbd60791ee86fe09f07fc9ed85be3654f7aa5a310baafd9053440952619e2bc9 vendoo/lib/security.mjs
2fd970a6a357a26211f0b9bcf432e59e79f73dc9a4cd35f88cca939655eefdff vendoo/lib/structured-logger.mjs
ddb9c7677600795a4adf8a19a7525b7551455459d16eed4cdfbe751ef9ddf0eb vendoo/lib/zip.mjs
2924f4e8abe5ebbd099fe1ceb2bc6ceb4bdda55fa3e57dd299cfc05d310a9246 vendoo/local-ai/start-local-flux.ps1
7c6176d8311b1ba9d511beb40edd41b8248e61c298528bbec3f9ef1171856c05 vendoo/local-ai/stop-local-flux.ps1
5f220a2dca02cc0764f6d0157677611b26c88860b48367eb661b6e47a1b92265 vendoo/local-ai/workflows/vendoo_flux_schnell_api.json
c848163a1cf38336947778d73c3b7f4039771270a4cf974352b0ea85e7879415 vendoo/package-lock.json
3d70a7f7d0d100d3ce336f130f1e7a7de3e2244dbf8fbcfd1d8e3f06d254b6da vendoo/package.json
3da71dd28cb25c7c7317b9061855d40c6a3ab8bc39391963b49ee1e707f838e5 vendoo/platforms/ebay-de.mjs
cc1ca2b4384c8c548bf755dc33101d248541bf893c3d5f35369961f904afcc00 vendoo/platforms/ebay-ka.mjs
fa52b247dd758aeee06120499bd1ae6c53e9f460f8bd7762b8f06141b201e32b vendoo/platforms/etsy.mjs
5c925e3934a4c9e2f26dc15b3449a249f5ce20ecebbd459b15365a34804824d6 vendoo/platforms/vinted.mjs
a2ea3f5f56dba8bd4d23fa54a26fd941567b4febdd1ed1b4e9f5bcc1c9786e53 vendoo/public/android-chrome-192x192.png
46ea6ba4ca6ca2352f37353b8bc4ca258935d29ecb8d3c9b133a48ea75c0c58f vendoo/public/android-chrome-512x512.png
4177569df5648213a0f8d65a5c0a9ae2c4f07ce28974a318ac03cf8c1b4e4a9e vendoo/public/app.js
e0e7b8ef01c36f0625b6157aa46bd69de05c17be0b054208fb635d6507b52154 vendoo/public/apple-touch-icon.png
a2ea3f5f56dba8bd4d23fa54a26fd941567b4febdd1ed1b4e9f5bcc1c9786e53 vendoo/public/brand/favicons/android-chrome-192x192.png
46ea6ba4ca6ca2352f37353b8bc4ca258935d29ecb8d3c9b133a48ea75c0c58f vendoo/public/brand/favicons/android-chrome-512x512.png
e0e7b8ef01c36f0625b6157aa46bd69de05c17be0b054208fb635d6507b52154 vendoo/public/brand/favicons/apple-touch-icon.png
a0f1e01de4e8215e690c1ce869fecaae9d7ba3cc95883340a53ff38f6be52ce0 vendoo/public/brand/favicons/browserconfig.xml
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b vendoo/public/brand/favicons/favicon-16x16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 vendoo/public/brand/favicons/favicon-32x32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 vendoo/public/brand/favicons/favicon-48x48.png
15bf8dd655b34a8015447e834d387af12685238ede598f5f0e7927eea2933483 vendoo/public/brand/favicons/favicon.ico
2daa93cca0ad2c0cab90a9e8ad4ea0ae4b64feeb68c422954020d17e2376a381 vendoo/public/brand/favicons/html-snippet.txt
3798313cc939d9fa582a92638356abfcfc8f8b4f143d9434b7012446195e6937 vendoo/public/brand/favicons/mstile-150x150.png
c372675942caa5010340f21fe521adc72af537d909008731976820fd84604d42 vendoo/public/brand/favicons/site.webmanifest
b2dc767e7a01395d23a7f3f5915324db1a7d1912bac60470d2f7c10815895173 vendoo/public/brand/icons/vendoo-icon-120x120.png
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf vendoo/public/brand/icons/vendoo-icon-128x128.png
d276f50b298e4dfcbba9147550463aee498531280399167d1e9774aa8e5f7e21 vendoo/public/brand/icons/vendoo-icon-144x144.png
3798313cc939d9fa582a92638356abfcfc8f8b4f143d9434b7012446195e6937 vendoo/public/brand/icons/vendoo-icon-152x152.png
47122dc91010721e2692d11986f0b91d9b76634130a95723e92b2a070268d16f vendoo/public/brand/icons/vendoo-icon-167x167.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b vendoo/public/brand/icons/vendoo-icon-16x16.png
e0e7b8ef01c36f0625b6157aa46bd69de05c17be0b054208fb635d6507b52154 vendoo/public/brand/icons/vendoo-icon-180x180.png
a2ea3f5f56dba8bd4d23fa54a26fd941567b4febdd1ed1b4e9f5bcc1c9786e53 vendoo/public/brand/icons/vendoo-icon-192x192.png
3f2517cfd215cb624ed639d60b064dfa5e88ce71eb7bbebbbfaa70b3d62556db vendoo/public/brand/icons/vendoo-icon-256x256.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 vendoo/public/brand/icons/vendoo-icon-32x32.png
cae3eb737c8ad3a82a679b09d33d991b501bf482e0132e99aa1b8ad064e472b4 vendoo/public/brand/icons/vendoo-icon-384x384.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 vendoo/public/brand/icons/vendoo-icon-48x48.png
46ea6ba4ca6ca2352f37353b8bc4ca258935d29ecb8d3c9b133a48ea75c0c58f vendoo/public/brand/icons/vendoo-icon-512x512.png
bc85af557be532dcce6beb82cf9bd61af683666b00fb61e4b2069f78e60a9a33 vendoo/public/brand/icons/vendoo-icon-64x64.png
01d59b665bc90dddbd34221e3a2ec3af11bff6fb328aab2c9947c03d74b0465d vendoo/public/brand/icons/vendoo-icon-72x72.png
ed3dfa59e989b154fac88a3c72ac840290ee3e1565d44aa75596bf0055c74020 vendoo/public/brand/icons/vendoo-icon-96x96.png
46ea6ba4ca6ca2352f37353b8bc4ca258935d29ecb8d3c9b133a48ea75c0c58f vendoo/public/brand/icons/vendoo-icon-original-1254.png
8fd9901e07dc9172d162706511ac8dcce220a4c907cb3efa9940c9c13fa32526 vendoo/public/brand/logo/vendoo-logo-cropped.png
3f39371abd1efa6cc8366aac9a6d067f3339b8f2a2da77ab8a26c6bdcf8c4fce vendoo/public/brand/logo/vendoo-logo-original.png
b56d07515f6220de7fd0cb149fed598a7361c985ae6ca7cb14329a99e8947aee vendoo/public/brand/logo/vendoo-logo-transparent.png
e83921d2af9930ab27df1abe64374cb9311189bfaaa951068109177443571a07 vendoo/public/brand/logo/vendoo-wordmark-transparent.png
1711a9387f2d6e75797b77c8daa92b94d7a15e128476e4b8aa9d54ccb0692a0e vendoo/public/core/api-client.js
f30395399a5c6d7e0a884b22f28f7648e6343695cee9960d6ff13b34de7b48f1 vendoo/public/core/frontend-module-registry.js
fb3dbcd03f7ed15b773b582c2a2b785c3040d3319aba5b7c682a7e74e1cf3b4e vendoo/public/core/safe-dom.js
38aa57d13aeb3ab70babcb903bfee71e47d80932ed24a73267c13ff81c24e3ba vendoo/public/design-system/theme-contract.json
308f1c0e2ed1de34aa11545a1a660aab02631e422d6c6945e3203d11666784fc vendoo/public/design-system/theme-runtime.js
4d69e2cb6b7f9f63b54d708a5d8b1ebefcdcb9f88a977053db5031c05b098464 vendoo/public/design-system/tokens/source.json
4a9e65edeaee3421edc3dd4831230062494f1a42f8495f4cb979fde8664d06c4 vendoo/public/design-system/tokens.css
15bf8dd655b34a8015447e834d387af12685238ede598f5f0e7927eea2933483 vendoo/public/favicon.ico
5157f9a0acad9e663d84e1b064a4b626ed61d08f3472ad058848a076bc7074b4 vendoo/public/index.html
da7f1b6488e33c9ff94323d2da3bdcea91e386484c11e5202432e567721704b4 vendoo/public/login.html
e37558ee9612a36db8a19999fbb320f1c249a8e155f94c83a82926bec920f989 vendoo/public/login.js
59291f75eca405e3856bafea76cc601d681060eb6b36bf82a4be3c3ab7eac290 vendoo/public/mobile-upload-expired.html
f046f166d89fc32774b87deb02e6d144fd2f40c0925aac67487e5b7c489a0ec1 vendoo/public/mobile-upload.css
6152e4fe715efbf8fd6a7c4286f23172bc3cf15dde085e5e4f7389ad5e65ad73 vendoo/public/mobile-upload.html
f13846801a8493aa43df6ec3d78b826b21b59e8f21d47735f68fd0b278e440c7 vendoo/public/mobile-upload.js
01f2bd124257220005032bf234d122b9942fdd8fd57ed8195748b2fb1f5a5cfb vendoo/public/modules/README.md
2d7a004db3e22b30ad3a682ba445bcee3fc1c5f0ed5e8fee45b5892c5b335e51 vendoo/public/modules/theme-manager/theme-manager.css
0edc61f0c2bb604c3adc40813b18fe5ca8d9b846ec2a3d9f406ae26ae313d3ee vendoo/public/modules/theme-manager/theme-manager.js
e0a6c981d4231eab26d981be62647d0e6f89e05e8371baad121348202ad54f49 vendoo/public/style.css
ff525e0af963e6f54636cfdc1bd2d045aaf82e7b0199755eb5cdf4c52110be2e vendoo/public/vendoo-icons.js
cc90bb9042d7f3c5b73a061c4621f36cf44c8841d35083c3033bae725d8525c0 vendoo/scripts/docker-backup.sh
20e7590a7633b6c61086a5596d0bec1d343f0ff0eecc444ac932130ff363e258 vendoo/scripts/docker-entrypoint.sh
50d93e7f9f71fa72071e5b2f3c63a548e4252c8096f6f8fa78342e5cf51db5c9 vendoo/scripts/docker-restore.sh
9a692ace2e8f92ff245be890277a74541c252e295591818597b8cfe08b3176a1 vendoo/scripts/github-deploy.ps1
00f950df71ddd4c5f62385529620cd85bfc73fb54e991489cedee05217ebe556 vendoo/scripts/github-deploy.sh
0a9bafc79c1c5d59fb9b51ebc34c00eec4a4e9a5e873ce1818f50f3ab983da70 vendoo/scripts/install-local-flux.ps1
2924f4e8abe5ebbd099fe1ceb2bc6ceb4bdda55fa3e57dd299cfc05d310a9246 vendoo/scripts/runtime-start-local-flux.ps1
7c6176d8311b1ba9d511beb40edd41b8248e61c298528bbec3f9ef1171856c05 vendoo/scripts/runtime-stop-local-flux.ps1
1a5736cf5fccc991df122163977c2eac80281bd99a54a5680b3d7eae99e4b79d vendoo/scripts/start-local-flux.bat
3bf3aa74f5cc1f2946bb2da637eb30fe8daec783a32f9721ebb0468e20df90bd vendoo/scripts/uninstall-local-flux.ps1
241b006d4066a68e330e26c8e38a041559b4e5c1368ad8cf3db5e2f63d6d8397 vendoo/server.mjs
3c33e7042bf4e95fa56a5e163a42f156b7995e7d89fef9e8db7d48577037828f vendoo/setup-gui.ps1
cf4519ce5adc01f05458e3286e86f3a419cceaff5fcdd869a1d07f1c1d1a0d8c vendoo/setup.bat
9658fe68ddff2903505b92998a9e78385dc73dd269804dc5a7447099b8a0457f vendoo/setup.ps1
24f9614b10f0a970f5233d9ac7083bca6c3d305b37ff29b57a5c21473b7f30a7 vendoo/setup.sh
90485a16e3468cb9a6750646700fbb036cb9ac410e9b8bd5c582f7b923bf3c31 vendoo/tools/build-release.mjs
ac8440bce2659a035302609722f1dfed5d125223376cd575ffc0636397c94b54 vendoo/tools/generate-design-tokens.mjs
294659f2beb607540abbc3d6b4a1658525448a42f8880f2b282081a259c4e35b vendoo/tools/prepare-git-staging.mjs
8f9ede5f112ee03323db3a6c73aee00b7037f5139dad241b11baf5f0e9cee4e0 vendoo/tools/verify-config-store.mjs
5752f6edb956696781da8bddb1c1848d26941fbed5a524691653c84c88c34bff vendoo/tools/verify-db-migrations.py
3745de55a110d8254983b096c6afab196ddaec7f1153cd2f34c1e480b15aa33e vendoo/tools/verify-deployment-1.32.0.mjs
44f6b349b722e5a83d4725c4879fa1a9383f59ab5634c49d3d7d9d7aa0cd5e12 vendoo/tools/verify-deployment-1.33.0.mjs
cbd91b45d97e11bd4f5ca2f9d2edf2b5931cb2aa336cb71afc30aad9cffbe1e0 vendoo/tools/verify-deployment-1.34.0.mjs
01a43040a95cdac40703f49031acd9267cdba99d9027a51718f35ffb643237fc vendoo/tools/verify-deployment-1.34.2.mjs
906767e574c06aedebb2d7797150bda2f1e4c4536e8f82f4c7de2e3cc8398c8e vendoo/tools/verify-deployment-1.34.3.mjs
71d00227a59592cc0ad8ba321c63350ec25748ef965d8cd0eff1317738c7fba8 vendoo/tools/verify-deployment-1.35.0.mjs
b65eec7fd54e1459b363d99d20f9438ae5bc4b518e775de8b97e33e89a382e42 vendoo/tools/verify-deployment-1.36.0.mjs
22a5ba1951b2e8dbc924e60aaff8be7c41189ae7b30de9ecf50d0b741e84e13a vendoo/tools/verify-deployment-1.37.0.mjs
1f052446f6c9627420afeb48aa09771b61f9e08ba573f6a0651b2843ef0b79f8 vendoo/tools/verify-git-safety-regression.mjs
5bba3d7ae042b0bcf4eb56bacb3f6e41e1b0e00cadd7666505792ba6748cc987 vendoo/tools/verify-git-safety.mjs
2f8d687319619240efe5849c276f7723e69755c66aa3b9609e41fdf0cda01e55 vendoo/tools/verify-git-staging.mjs
1d4351e4a827e718766a1677ddfbc3771a91942d0d5a93753e39f1b99c68a4dd vendoo/tools/verify-hotfix-1.23.2.mjs
44c95844422be3deaad6054ee3f0cced9c25986815d976e0c64b042d0c2c5e1e vendoo/tools/verify-installer-shell.sh
cab03e98687af87f359f6424d440fc0b644da97b3c614509b8c7d008d4b18a8d vendoo/tools/verify-platform-architecture-1.35.0.mjs
732bb15431746a829e45ae55c695360cbf1dd21d4fc3be26a98f35708d571e84 vendoo/tools/verify-platform-architecture-1.36.0.mjs
ee8ae7bed4e93a2ef278662552a4ae5d751306aad7133a93f380bbf2a5d5a28c vendoo/tools/verify-platform-architecture-1.37.0.mjs
36e35fedb08923c22fd8551389d33432b66dbd4215d95c594ef29bfc790c98e0 vendoo/tools/verify-release-1.25.0.mjs
89621694b7bad18b6f3f1ac1956032f64112c40d3edc069ca581dc813d57d628 vendoo/tools/verify-release-1.25.1-static.mjs
c908f5186cf2d71ef83d5e649327ae19965568933acfb32057ca00d29cf890bc vendoo/tools/verify-release-1.25.1.mjs
e31a055d2ebb8e439f5b0e0235a71dacecb891e299377cfbbcfa8a32f53a85b0 vendoo/tools/verify-release-1.26.0-static.mjs
7e107b5f9a1b4ee381ff31105feb6d38dda5c40e4afe105a955badc36e6b8d10 vendoo/tools/verify-release-1.26.1-static.mjs
d9a75c45f40d857c84790d51dca2fd088c3851ca250405871a7e32773918c66e vendoo/tools/verify-release-1.27.0.mjs
3989e3ec236c1aa4c387b26cc15e04cf200a018e29c095321acf826c6bae4d66 vendoo/tools/verify-release-1.28.0.mjs
7d196d913a697248ab1233907fed56c10329cf201e3bdc173bca73cb02755369 vendoo/tools/verify-release-1.29.0.mjs
3f30260dabbdf0fa7b042381cb9e24f840d0c3ddbc44fe309763789a7d14afb7 vendoo/tools/verify-release-1.30.0.mjs
b1ceed5dfc17dbd3b038b7168e61076e4d39a0f1d67e2b87677a91c4dbb2daff vendoo/tools/verify-release-1.31.0.mjs
a372258b97aa68d59a1fe0fd3f380d019c59412d5c408a6064f437d5cfc6e709 vendoo/tools/verify-security-1.31.0.py
08820d9bb7be1dec496c04e9ea4a39b2ebb84d373a9481136610d16dea0edde3 vendoo/tools/verify-security-foundation-1.37.0.mjs
31a120622ce8bb8451014f2662366f81abd28d0f3be59adfe35d17e0ada1838f vendoo/tools/verify-slice30-mock.mjs
20957a4a038b9afdb01a8c98b881644daf793d2a6bb778a4c8e04780687d00e4 vendoo/tools/verify-slice31-image-editor.mjs
21061ed5dc88feef48e80efffd9a1054d38598dce5a5d3f9f6bde39b539b83f0 vendoo/tools/verify-slice32-batch.mjs
0f05b1ac3b686cf535bcfb3e6f6df24a29c3429ade1b3c666c1b99abb1a7311b vendoo/tools/verify-slice32-image-render.mjs
c9aa6693aa93ff1f220a2ce3bc35ef714a0b18a53eae0f907879fc92c66c1e38 vendoo/tools/verify-theme-manager-1.36.0.mjs
1e61c4b180aa09de3dae9e72aef313b09a6f422229f180984b69a8d226e7cd8d vendoo/tools/verify-theme-manager-1.37.0.mjs
0f3f684019763a14f5fbaec42e42c680cf748d930d46cd607fc61eb413ca4553 vendoo/tools/verify-ui-contracts-1.26.1.mjs
63bef319d33f6998c4c378f12710733d98f2007e8b0ff313cb80c978320800f4 vendoo/update-manifest.json
@@ -1,27 +0,0 @@
.git
.gitignore
.env
.env.*
!.env.example
node_modules
npm-debug.log*
*.log
*.db
*.db-*
*.sqlite
*.sqlite3
backups
operations
logs
uploads
runtime
data
local-ai/comfyui
local-ai/downloads
local-ai/.env.local-flux
MockupDesign
*.zip
FILE_CHECKSUMS_SHA256.txt
release-output
.vendoo-github-state.json
operations/first-admin-code.txt
@@ -1 +0,0 @@
* @Masterluke77
@@ -1,27 +0,0 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
time: '05:00'
timezone: Europe/Berlin
open-pull-requests-limit: 5
groups:
npm-production:
dependency-type: production
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
time: '05:30'
timezone: Europe/Berlin
open-pull-requests-limit: 5
- package-ecosystem: docker
directory: /
schedule:
interval: monthly
time: '06:00'
timezone: Europe/Berlin
open-pull-requests-limit: 5
@@ -1,20 +0,0 @@
## Änderung
<!-- Was wurde geändert und warum? -->
## Sicherheit und Daten
- [ ] Keine `.env`, Tokens, Datenbanken, Uploads, Backups, Logs oder Modelle enthalten
- [ ] Bestehende Benutzer- und Artikeldaten bleiben erhalten
- [ ] Originalbilder werden nicht überschrieben
- [ ] FASHN VTON / Virtual Try-on wurde nicht wieder eingeführt
## Prüfung
- [ ] `npm ci`
- [ ] `npm run verify:git`
- [ ] `npm run check`
- [ ] `npm run verify:architecture`
- [ ] `npm run verify:deployment`
- [ ] `npm run verify:db`
- [ ] Windows-/Docker-/Browser-Abnahme dokumentiert oder ausdrücklich als offen markiert
@@ -1,86 +0,0 @@
name: Vendoo CI
on:
push:
branches: [main, develop, 'feature/**', 'release/**', 'hotfix/**']
pull_request:
branches: [main, develop]
permissions:
contents: read
concurrency:
group: vendoo-ci-${{ github.ref }}
cancel-in-progress: true
jobs:
quality:
name: Syntax, Sicherheit und Release-Gates
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- name: Repository auschecken
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Node.js 22 aktivieren
uses: actions/setup-node@v4
with:
node-version: '22.x'
cache: npm
- name: Abhängigkeiten reproduzierbar installieren
run: npm ci
- name: Git-Sicherheitsgate
run: npm run verify:git
- name: Git-Sicherheitsgate Regressionstest
run: npm run verify:git-regression
- name: Git-Staging-Filter Regressionstest
run: npm run verify:git-staging
- name: Syntaxprüfung
run: npm run check
- name: Plattformarchitektur und Design Tokens prüfen
run: npm run verify:architecture
- name: Theme Manager, Accessibility und Komponenten-Tokens prüfen
run: npm run verify:themes
- name: Security, Secrets und Observability prüfen
run: npm run verify:security
- name: Deployment-Gate
run: npm run verify:deployment
- name: Persistenten Konfigurationsspeicher prüfen
run: npm run verify:config
- name: Geführte Shell-Installer simulieren
run: npm run verify:installer-shell
- name: Datenbankmigrationen prüfen
run: npm run verify:db
- name: Docker-Compose-Dateien validieren
run: |
cp .env.example .env
python - <<'PY'
from pathlib import Path
p=Path('.env')
s=p.read_text()
s=s.replace('VENDOO_SETUP_TOKEN=', 'VENDOO_SETUP_TOKEN=ci-only-not-a-production-secret-1234567890')
s=s.replace('VENDOO_DOMAIN=', 'VENDOO_DOMAIN=vendoo.example.invalid')
p.write_text(s)
PY
docker compose -f compose.yaml config -q
docker compose -f compose.yaml -f compose.bind-mounts.example.yaml config -q
docker compose -f compose.vps.yaml config -q
rm -f .env
- name: Docker-Image testweise bauen
run: docker build --pull --tag vendoo:ci .
@@ -1,144 +0,0 @@
name: Vendoo Release
on:
release:
types: [published]
permissions:
contents: read
concurrency:
group: vendoo-release-${{ github.event.release.tag_name }}
cancel-in-progress: false
env:
REGISTRY: ghcr.io
IMAGE_NAME: masterluke77/vendoo
jobs:
release-assets:
name: Release-Paket und Prüfsummen
permissions:
contents: write
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Repository auschecken
uses: actions/checkout@v6
- name: Node.js 22 aktivieren
uses: actions/setup-node@v4
with:
node-version: '22.x'
cache: npm
- name: Abhängigkeiten installieren
run: npm ci
- name: Release-Tag gegen Paketversion prüfen
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
EXPECTED="v$(node -p "require('./package.json').version")"
test "$RELEASE_TAG" = "$EXPECTED" || { echo "Release-Tag $RELEASE_TAG passt nicht zu $EXPECTED." >&2; exit 1; }
- name: Vollständige Prüfung
run: |
npm run verify:git
npm run verify:git-regression
npm run verify:git-staging
npm run check
npm run verify:architecture
npm run verify:themes
npm run verify:security
npm run verify:deployment
npm run verify:config
npm run verify:installer-shell
npm run verify:db
- name: Release-Staging erzeugen
run: node tools/build-release.mjs
- name: ZIP und SHA-256 erzeugen
id: package
shell: bash
run: |
PACKAGE_NAME="$(cat release-output/RELEASE_NAME.txt)"
cd release-output
zip -r -9 "${PACKAGE_NAME}.zip" "${PACKAGE_NAME}"
sha256sum "${PACKAGE_NAME}.zip" > "${PACKAGE_NAME}.zip.sha256.txt"
echo "package_name=${PACKAGE_NAME}" >> "$GITHUB_OUTPUT"
- name: Assets an GitHub Release anhängen
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }}
PACKAGE_NAME: ${{ steps.package.outputs.package_name }}
run: |
gh release upload "$TAG" \
"release-output/${PACKAGE_NAME}.zip" \
"release-output/${PACKAGE_NAME}.zip.sha256.txt" \
--clobber
- name: Build-Artefakte sichern
uses: actions/upload-artifact@v4
with:
name: ${{ steps.package.outputs.package_name }}
path: |
release-output/${{ steps.package.outputs.package_name }}.zip
release-output/${{ steps.package.outputs.package_name }}.zip.sha256.txt
if-no-files-found: error
retention-days: 30
container:
name: GHCR-Container veröffentlichen
permissions:
contents: read
packages: write
attestations: write
id-token: write
runs-on: ubuntu-latest
timeout-minutes: 35
steps:
- name: Repository auschecken
uses: actions/checkout@v6
- name: Docker Buildx aktivieren
uses: docker/setup-buildx-action@v3
- name: Bei GHCR anmelden
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Container-Metadaten erzeugen
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}},value=${{ github.event.release.tag_name }}
type=semver,pattern={{major}}.{{minor}},value=${{ github.event.release.tag_name }}
type=raw,value=latest,enable=${{ !github.event.release.prerelease }}
- name: Container bauen und veröffentlichen
id: push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64
provenance: true
sbom: true
- name: Container-Provenienz attestieren
uses: actions/attest@v4
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
@@ -1,84 +0,0 @@
# Secrets and local configuration
.env
.env.*
!.env.example
!.env.docker.example
*.pem
*.key
*.p12
*.pfx
*.crt
# Dependencies
node_modules/
# SQLite runtime data
db/*.db
db/*.db-shm
db/*.db-wal
db/*.sqlite
db/*.sqlite3
# User and runtime data
uploads/*
!uploads/.gitkeep
backups/
logs/
tmp/
temp/
sessions/
data/
docker-data/
*.log
# OS and editor files
.DS_Store
Thumbs.db
desktop.ini
.vscode/
.idea/
# Local overrides
compose.override.yaml
docker-compose.override.yml
# Local AI runtimes and downloaded model data
local-ai/comfyui/
local-ai/downloads/
local-ai/extract-temp/
local-ai/fashn-vton/.venv/
local-ai/fashn-vton/engine/
local-ai/fashn-vton/weights/
local-ai/fashn-vton/outputs/
local-ai/fashn-vton/runtime/
local-ai/fashn-vton/hf-cache/
local-ai/fashn-vton/fashn-vton-*.zip
local-ai/fashn-vton/python311/
local-ai/fashn-vton/uv/
local-ai/fashn-vton/uv-cache/
local-ai/fashn-vton/downloads/
# Local update, rollback and slice archives
updates/
# Operations Center runtime
operations/staging/
operations/updates/
operations/rollback/
operations/apply-*/
operations/pending-operation.json
operations/last-operation.json
# Deployment assistant state
.vendoo-install-mode
runtime/
# Generated deployment and release output
release-output/
*.release.zip
*.release.sha256.txt
.vendoo-github-state.json
# First-run and local installer state
operations/first-admin-code.txt
config/local/
@@ -1,9 +0,0 @@
registry=https://registry.npmjs.org/
audit=false
fund=false
strict-ssl=true
prefer-offline=true
fetch-retries=5
fetch-retry-factor=2
fetch-retry-mintimeout=10000
fetch-retry-maxtimeout=120000
@@ -1,730 +0,0 @@
# Changelog
## 1.37.0 Security, Secrets & Observability Foundation
### Neu
- `vendoo.security` als natives Kernmodul.
- AES-256-GCM-verschlüsselter Secret-Speicher mit separatem Master-Key.
- Automatische Migration vorhandener Runtime- und SMTP-Secrets mit Sicherungskopie.
- Strikte Script-CSP ohne Inline-Skripte und Inline-Eventhandler.
- Request- und Correlation-IDs sowie strukturierte JSON-Telemetrie.
- Zentrale Input-Schema-Validierung für neue Kernel-Routen.
- Erweitertes Security-Dashboard für Secret-Provider, CSP und Requeststatus.
- SMTP-Zertifikatsprüfung standardmäßig aktiv.
- GitHub Draft Pull Request #10 für `release/1.37.0-security-foundation`.
### Kompatibilität
- Keine Datenbankablösung und keine destruktive Migration.
- Windows, Docker, NAS und VPS bleiben unterstützt.
- Theme Manager und vorhandene Daten bleiben erhalten.
## 1.36.0 Secure Theme Manager, Accessibility & Component Token Foundation
### Neu
- `vendoo.themes` als erstes natives Fachmodul auf dem Plattformkernel.
- Persönliche Theme-Präferenzen pro Benutzer mit Theme, UI-Dichte und reduzierter Bewegung.
- Sichere Theme-Profile für Administratoren mit Basis-Theme, Token-Overrides, Import, Export und Systemstandard.
- Live-Vorschau im Browser; Speichern erst nach expliziter Bestätigung.
- Serverseitige Validierung aller Theme-Werte und WCAG-orientierte Kontrastprüfung zentraler Text-/Oberflächenpaare.
- Light, Dark, System und High Contrast als integrierte Modi.
- 42 typisierte Design Tokens, darunter erste Komponenten-, Fokus- und Touch-Target-Tokens.
- Tokenisierte Buttons, Eingabefelder, Karten, Dialoge und Fokuszustände.
- Deny-by-default API-Verträge für Theme-Routen sowie getrennte Benutzer- und Administrator-Policies.
- Audit-Protokoll für persönliche Präferenzen, Theme-Profile und Systemstandard.
- Eigenes `verify:themes`-Gate in lokaler Prüfung, GitHub CI und Release-Workflow.
- GitHub Draft Pull Request #9 für `release/1.36.0-theme-manager`.
### Sicherheit und Kompatibilität
- Keine freie CSS-, JavaScript-, URL- oder Dateipfad-Eingabe.
- Unbekannte Tokens und Theme-IDs werden abgewiesen.
- Normale Benutzer dürfen ausschließlich ihre eigene Darstellung ändern.
- Systemstandard und benutzerdefinierte Profile erfordern administrative Berechtigung.
- Bestehende Daten, Benutzer, Artikel, Uploads, Backups und FLUX-Daten bleiben erhalten.
- Kein Reset, keine Framework-Migration und keine Datenbankablösung.
## 1.35.0 Modular Platform Kernel, Design-System Contracts & Security Architecture Foundation
### Neu
- Modularer Plattformkernel mit Lifecycle, Event Bus, Feature Flags, Modul- und Policy-Registry.
- Zwölf bestehende Fachbereiche als validierte `legacy-bridge`-Module mit expliziten Abhängigkeiten, Capabilities und Ownership.
- Deny-by-default Route Registry: neue Kernel-Routen benötigen Besitzer und explizite Policy.
- Administrativ geschützte Plattform-, Modul- und Theme-Vertragsendpunkte.
- Kernel-Healthcheck in `/readyz` und geordneter Kernel-Shutdown.
- Versionierte Design-Token-Quelle mit 33 Tokens für Light, Dark und High Contrast.
- Deterministischer Token-Generator und browserseitige Theme Runtime.
- Sichere Theme-Definitionen: nur freigegebene Farb- und Dimensionswerte, kein freies CSS/JS.
- Modul-JSON-Schema, Architekturgrenzen, Migrationsroadmap und Security-Architekturdokumentation.
- Neues `npm run verify:architecture` mit Zyklus-, Policy-, Event-, Theme- und Token-Regressionstests.
- GitHub Draft Pull Request #7 für `release/1.35.0-platform-kernel`.
### Kompatibilität
- Kein Reset, keine Framework-Migration, keine Datenbankablösung.
- Windows-Lokalbetrieb, Docker, NAS, VPS, Zero-Edit-Installer und Git-Sicherheitsgate bleiben erhalten.
- Bestehende CSS-Variablen bleiben über eine Token-Kompatibilitätsbrücke funktionsfähig.
- Bestehende Routen werden in 1.35.0 noch nicht massenhaft verschoben; die Migration erfolgt fachmodulweise.
## 1.34.3 Git-Staging Update-Archiv-Ausschluss Hotfix
### Behoben
- Der lokale Ordner `updates/` wird als Update-, Rollback- und Slice-Artefaktspeicher behandelt und nicht nach GitHub oder in Release-Staging-Verzeichnisse übernommen.
- Alte Sicherungskopien wie `updates/backups/.../setup.bat`, `setup.ps1` oder `scripts/install-local-flux.ps1` lösen das Git-Sicherheitsgate nicht mehr aus, weil sie bereits vor dem Scan ausgeschlossen werden.
- Die aktiven Installationsdateien im Projektroot und unter `scripts/` bleiben Teil des Quellimports.
- Das Git-Sicherheitsgate blockiert `updates/` weiterhin, falls ein fremder Kopierweg den Ordner dennoch in das Staging einschleust.
- `.gitignore` schützt den lokalen Updateverlauf zusätzlich vor versehentlichen Commits.
### Qualitätssicherung
- Regressionstest mit den drei konkret gemeldeten Pfaden aus `slice22_1_20260707-194953`.
- Release-Builder und GitHub-Deploy-Assistent verwenden weiterhin dieselbe Filterfunktion.
- Neuer Importbranch `release/1.34.3-initial-import` und Draft Pull Request #6.
## 1.34.2 Git-Sicherheitsdiagnose & gemeinsamer Staging-Builder
### Behoben
- Die Meldung `Git-Sicherheitsgate fehlgeschlagen (4)` wird nicht mehr ohne Detailzeilen ausgegeben. Der Windows-Assistent fängt stdout und stderr getrennt ab und zeigt jeden konkreten Treffer an.
- Der vollständige Fehlerbericht wird unter `logs/github-deploy-safety-report.txt` gespeichert und unter Windows automatisch im Editor geöffnet.
- Windows, Linux und macOS verwenden denselben Node-basierten Staging-Builder statt unterschiedlicher Robocopy-/rsync-Regeln.
- Lokale `.env.*`-Dateien, Operations-Daten, Uploads, Backups, Logs, Datenbanken, Schlüsseldateien und FLUX-/ComfyUI-Laufzeitdaten werden vor dem Sicherheitsgate automatisch aus dem temporären Git-Staging ausgeschlossen.
- `.env.example` und `.env.docker.example` bleiben als sichere Vorlagen enthalten.
- Der Staging-Builder leert nur den Arbeitsbaum des temporären Klons und erhält dessen `.git`-Verzeichnis vollständig.
### Qualitätssicherung
- Neuer plattformübergreifender Git-Staging-Regressionstest.
- Der Test belegt, dass lokale Secrets und Laufzeitdaten ausgeschlossen, öffentliche Vorlagen übernommen und `.git` nicht verändert werden.
- CI und Release-Workflow führen den Staging-Regressionstest zusätzlich zum Secret-Regressionstest aus.
- Neuer Importbranch `release/1.34.2-initial-import` und Draft Pull Request #5.
## 1.34.1 Git-Sicherheitsgate Windows Hotfix
### Behoben
- Windows-Pfade werden im Git-Sicherheitsgate mit `fileURLToPath(import.meta.url)` in echte Dateisystempfade umgewandelt.
- Der Sicherheitscheck scannt den vollständigen Import-Arbeitsbaum und nicht nur bereits von Git verfolgte Dateien.
- Noch unversionierte `.env.local`, `.env.production`, Token-Dateien und sonstige Secrets werden vor `git add` erkannt.
- Node.js ist für den sicheren Import verpflichtend; ein stilles Überspringen des erweiterten Scans ist nicht möglich.
## 1.34.0 GitHub CI/CD & Zero-Edit Installation Foundation
### Installation
- Grafischer Windows-Installationsassistent für lokalen Node.js-Betrieb und Docker Desktop.
- Geführte Linux-/NAS-/VPS-Konfiguration ohne manuelles Bearbeiten von `.env` oder Compose-Dateien.
- Automatische Erzeugung und sichere Ablage des Erst-Admin-Setup-Codes.
- VPS-Modus mit integriertem Caddy-Reverse-Proxy und automatischem HTTPS.
- Konfiguration kann später über den Assistenten geändert werden, ohne bestehende Daten zu löschen.
- Persistenter Runtime-Konfigurationsspeicher für Eingabemasken im gehärteten read-only Container.
- Simulierbares Shell-Installer-Gate für Docker-, NAS- und VPS-Modus; dabei wurde die Standardwert-Abfrage gegen Prompt-Vermischung gehärtet.
### GitHub und Releases
- Git-Sicherheitsgate gegen Secrets, Datenbanken, Uploads, Backups, Logs, Runtime- und Modellordner.
- GitHub Actions für CI, Docker-Build, Release-Pakete, SHA-256 und GHCR-Images.
- Windows- und Shell-GitHub-Deploy-Assistent für kontrollierten Erstimport auf einen Release-Branch.
- Privater Branch `release/1.34.0-initial-import` und Draft Pull Request #3 real vorbereitet.
- Release-Pakete werden aus einem bereinigten Staging-Verzeichnis erzeugt und nicht als Binärdateien in die Git-Historie aufgenommen.
### Sicherheit
- GitHub Actions besitzen jobbezogen minimale Berechtigungen.
- GHCR-Images erhalten eine Provenienz-Attestierung auf Basis des tatsächlich veröffentlichten Image-Digests.
- Container-Registry-Veröffentlichung erfolgt nur bei veröffentlichten GitHub Releases und passendem Versionstag.
- Produktions-Secrets bleiben in `.env` beziehungsweise GitHub Environments und niemals im Repository.
## 1.33.0 Multiplatform Deployment Wizard & Flux/Admin Fixes
- Installationsziel-Assistent für Windows lokal, Docker Desktop, NAS/Portainer und VPS/Linux
- neues `setup.sh` für Linux-, NAS- und VPS-Zielsysteme
- Installationsmodus wird für Start, Update, Reparatur, Status und Deinstallation gespeichert
- Docker-Host-Gateway für einen getrennten FLUX/ComfyUI-Dienst
- FLUX Studio startet ohne automatische Bildauswahl
- Reset-Button leert den Arbeitsbereich, ohne Verlauf, Bilder oder Jobs zu löschen
- Benutzerbearbeitung auf stabile Event-Listener und Cachelogik umgestellt
- Passwortvalidierung vor dem Update und sanitisierte Benutzerantwort
## 1.32.0 Docker, NAS & Production Deployment Foundation
- produktionsgeeignetes, mehrstufiges Dockerfile mit Lockfile-Installation
- Compose mit getrennten persistenten Volumes, non-root, read-only und Healthcheck
- zentrale, konfigurierbare DB-/Upload-/Backup-/Operations-/Log-Pfade bei voller Windows-Kompatibilität
- `/readyz` mit SQLite- und Schreibpfadprüfung
- geordneter SIGTERM-/SIGINT-Shutdown mit WAL-Checkpoint
- geschütztes Erst-Admin-Setup über `VENDOO_SETUP_TOKEN`; übrige API bleibt bis zum Setup gesperrt
- konfigurierbare Proxy- und Cookie-Regeln
- produktive Allowlist für Browser-Extension-Origins
- Uploads nur angemeldet abrufbar und strengere Dateitypprüfung
- NAS-, Portainer-, Backup-, Restore-, Update- und Rollback-Dokumentation
- FLUX/ComfyUI bleibt getrennt und ist im Hauptcontainer standardmäßig deaktiviert
## 1.31.0 Mehrbenutzer- und Server-Sicherheitsgrundlage
- Fünf feste Rollen mit serverseitig erzwungenen Berechtigungen: Administrator, Manager, Editor, Publisher und Leser.
- Sichere Sitzungen mit absoluter und inaktiver Laufzeit, Widerruf, Benutzer-Sitzungsverwaltung und Login-Sperre.
- Bearbeitungssperren für Artikel mit automatischer Verlängerung und kontrollierter Freigabe.
- Filterbares und exportierbares Audit-Protokoll.
- Rate Limits, Host-/Origin-Freigaben, Request-IDs, CSP/Helmet und standardmäßige Bindung an localhost.
- Benutzer- und Sicherheitsoberfläche mit Rollenmatrix, aktiven Sperren und Sicherheitsstatus.
- Additive Migrationen; bestehende Artikel, Datenbank, Bilder und Einstellungen bleiben erhalten.
## 1.30.0 Operations Center: Backup, Restore, Updates & Extension-Diagnose
- Neue Betriebszentrale unter Admin → System mit Backup-, Update- und Extension-Diagnose-Tabs.
- Konsistente SQLite-Backups über die Backup-API statt Kopieren der geöffneten Datenbank.
- Vollbackups mit Uploads, optionaler `.env`, Manifest, SHA-256-Dateiprüfsummen und SQLite-Integritätsprüfung.
- Tägliche rotierende automatische Backups mit konfigurierbarer Uhrzeit, Aufbewahrung und Upload-Option.
- Verifizierte Wiederherstellung mit automatischem Sicherheitsbackup und bewusstem Offline-Anwenden.
- Update Center prüft Version, Pflichtdateien und verbotene Laufzeitdaten, bevor ein Paket vorbereitet wird.
- Setup-Menüpunkt 11 wendet vorbereitete Update-/Restore-Operationen an; Menüpunkt 12 führt den Rollback aus.
- Migrationsstatus und letzte Systemoperation sind in der Oberfläche sichtbar.
- Vendoo Link 1.9.0 sendet Diagnose-Heartbeats; Chrome, Edge, Firefox und Safari werden getrennt ausgewertet.
- Keine Datenbank, Uploads, `.env`, API-Schlüssel oder Modelle werden durch ein Update-Paket gelöscht.
## 1.29.0 Slice 34: Publishing Hardening
- plattformübergreifende persistente Publishing-Queue
- Doppelveröffentlichungsschutz und Idempotenzprüfung
- automatische Retry-Strategie und Neustart-Wiederaufnahme
- Fehlerzentrale, Ereignisprotokoll, externe IDs und Links
- eBay Sync, Update und Beenden über offizielle Inventory API
- Etsy Statusabgleich
- Extension-Aufträge für Vinted und Kleinanzeigen
- Scheduler an die gehärtete Queue angebunden
- Vendoo Link 1.8.0
## 1.28.0 Slice 33: Artikel Quality Center
- Neuer Hauptmenüpunkt **Qualitätscenter** mit Score, Noten AE, Blockern, Warnungen und Empfehlungen.
- Serverseitige Prüfung von Titel, Beschreibung, Pflichtfeldern, Preis, Organisation, Suchbegriffen und plattformbezogenen Vendoo-Profilen.
- Vollständige Bildprüfung mit Dateiexistenz, Lesbarkeit, Abmessungen, Format und Auflösungswarnungen.
- Erkennung möglicher Duplikate über gleiche SKU und Titelähnlichkeit.
- Plattformbereitschaft, Gebühren und geschätzter Erlös gemeinsam im Prüfbericht.
- Persistenter Score-Verlauf je Artikel mit Vergleich zur vorherigen Analyse.
- Filter, Suche und Pagination für bereite, blockierte und zu prüfende Artikel.
- AI-Verbesserungen für Titel, Beschreibung und Tags über den aktuell aktiven Text-AI-Provider.
- AI erzeugt ausschließlich Vorschläge; Änderungen werden erst nach sichtbarem Vorher-/Nachher-Vergleich und ausdrücklicher Bestätigung gespeichert.
- Keine automatische Erfindung von Produktmerkmalen, Marken, Schäden oder Lieferumfang.
## 1.27.0 Slice 32: Batch Image Factory
- Neuer Hauptmenüpunkt **Bildproduktion** als persistente Batch Image Factory.
- Mehrere Quellbilder direkt aus der zentralen Bildergalerie auswählen oder aus der Galerie übergeben.
- Acht integrierte Produktionsprofile für eBay, Vinted, Kleinanzeigen, Etsy, Instagram, Webshop und optimierte Originale.
- Eigene Produktionsprofile mit Zielgröße, Anpassung, Hintergrund, Format, Qualität und Dateinamensschema anlegen, bearbeiten und löschen.
- Mehrere Profile pro Auftrag erzeugen mehrere Ausgaben je Originalbild.
- Optionale Hintergrundentfernung mit Intensität sowie Wasserzeichen mit Text, Position und Deckkraft.
- Persistentes Job-Center mit 5/10/15 Aufträgen pro Seite, Pause, Fortsetzen, Abbruch, Gesamt-Retry und Einzel-Retry.
- Neustart-Wiederaufnahme für wartende und laufende Aufträge; pausierte Aufträge bleiben pausiert.
- Ergebnisse werden nicht destruktiv als neue Bildversionen unter `uploads/batch/` gespeichert und erscheinen automatisch in der Bildergalerie.
- Fertige Ergebnisse eines Auftrags können gesammelt als ZIP heruntergeladen werden.
- Bildrenderer um `contain`, `cover`, exakte Ziel-Canvas, Ausgabeordner und kontrollierte Dateinamen erweitert.
## 1.26.1 Stabilitäts-, Responsive- und Regression-Gate
- Zentrale Systemprüfung im Adminbereich ergänzt: SQLite-Integrität, Schreibrechte, UI-Dateien, FLUX-Workflow, Browser-Extensions, AI-Konfiguration und optionale ComfyUI-Erreichbarkeit.
- Öffentlichen, geheimnisfreien `/healthz`-Endpunkt für lokale Verbindungsüberwachung ergänzt.
- API-Client um Request-IDs, definierte Zeitlimits, einmaligen GET-Retry bei Netzwerk-/Serverfehlern und strukturierte Fehlerprotokollierung erweitert.
- Sichtbare Verbindungsleiste bei Serverausfall mit automatischer Wiederholungsprüfung ergänzt.
- Unbehandelte JavaScript- und Promise-Fehler werden lokal mit Build, Seite und Request-ID für die Diagnose erfasst.
- Responsive-Verhalten auf die tatsächlich verfügbare Workspace-Breite umgestellt; `ResizeObserver` vergibt Breitenklassen unabhängig von der Browserbreite.
- Globale Schutzregeln gegen horizontales Überlaufen von Formularen, Bildern, Vorschauen, Werkzeugleisten und langen Inhalten ergänzt.
- Neue statische Release- und UI-Vertragsprüfungen verhindern doppelte IDs, tote Navigation, fehlende Diagnoseelemente und veraltete Buildmarker.
- Keine Datenbankstruktur, Nutzerdaten, API-Schlüssel, Extensions oder FLUX-Modelle verändert.
## 1.26.0 Artikel-Navigation, Publish-Reparatur, Zoom-Galerie & Extension Center
- „Neues Listing“ konsequent in „Neuer Artikel“ und „Listing generieren“ in „Artikel generieren“ umbenannt.
- „Neuer Artikel“ als eigener Hauptmenüpunkt direkt unter dem Dashboard ergänzt; „Listings“ heißt in der Navigation jetzt „Artikel“.
- Publish-Datenaufbereitung gegen fehlerhafte ältere JSON-Felder gehärtet und einen Scope-Fehler im direkten Publish-Workspace behoben.
- Smart Copy öffnet wieder zuverlässig als Popup; die mittlere Publish-Fläche zeigt Titel, Beschreibung, Tags, Metadaten und Fotos.
- Medienvorschau um Fit-, 100-%-, Stufen- und Mausrad-Zoom sowie Verschieben bei Vergrößerung erweitert.
- Galerie-Auswahl und Favoriten auf kleine, konsistente Lucide-basierte SVG-Icons umgestellt.
- Gebührenrechner für private Verkäufer aktualisiert: eBay.de, Vinted und normaler Kleinanzeigen-Privatverkauf ohne Verkäuferprovision; Etsy separat als Shop-Kalkulation.
- Neuer Menüpunkt „Extensions“ mit Browsererkennung, Ein-Klick-Vorbereitung, Pfadkopie und Downloadpaketen für Chrome, Edge, Firefox und Safari.
- Safari-WebExtension-Quelle samt Xcode-Konvertierungsskript ergänzt.
- Doppelte Settings-ID und doppelten Galerie-Event-Listener bereinigt.
## 1.25.1 Adaptive Bildergalerie
- Galerie-Raster vollständig auf automatische Kartenbreiten mit `auto-fit` und Container Queries umgestellt.
- Die gesamte Bildfläche öffnet jetzt die Lightbox; die übergroße Vorschau-/Öffnen-Schaltfläche wurde entfernt.
- Auswahl und Favorit skalieren mit der Kartenbreite und bleiben sauber in den Bildecken ausgerichtet.
- Aktionsleiste auf vier kompakte, adaptive Bildaktionen umgestellt; auf sehr schmalen Karten werden nur Symbole gezeigt.
- Auswahlstatus wird zusätzlich an Karte und Bildfläche sichtbar, ohne das Motiv zu verdecken.
- Seitennavigation mit direkter Seitenauswahl und Bildbereich wird oberhalb und unterhalb der Galerie angezeigt.
- Listenansicht und schmale Bildschirmbreiten wurden im selben Komponentenmodell neu gehärtet.
## 1.25.0 Responsive Detail Editor, Gallery UX, Smart Copy Modal & FLUX Prompt Lab
- Listing-Bearbeiten reagiert jetzt auf die tatsächlich verfügbare Inhaltsbreite per Container Queries und bleibt auch mit Sidebar, Quill, Vorschau und Kontextkarten ohne horizontalen Überlauf bedienbar.
- Die zentrale Bildergalerie erhielt sauber ausgerichtete Auswahlfelder, Favoriten-Overlay, eine eindeutige Vorschauaktion, zweizeilige Titel und ein stabiles 2×2-Aktionsraster.
- Publish-Aktualisieren rotiert nicht mehr; während des Ladens werden ruhige Textzustände und `aria-busy` verwendet.
- Smart Copy öffnet wieder als eigenes responsives Arbeitsfenster mit Kopierfeldern, Fotos, Plattformstart und Veröffentlichungsstatus.
- FLUX Ergebnisse & Favoriten besitzen Pagination mit 5, 10 oder 15 Bildern pro Seite.
- Das FLUX Job-Center ist auf 5, 10 oder 15 Aufträge pro Seite begrenzt.
- Neues FLUX Prompt Lab: lokale Strukturierung oder AI-Veredelung über den aktuell aktiven Claude-, OpenAI-, OpenRouter- oder Ollama-Provider.
- Prompt Lab schützt auf Wunsch Motivmerkmale und vermeidet erfundene Texte, Logos und Wasserzeichen.
- Zusätzliche Breitenhärtung für Publish, Medienbibliothek, FLUX, Einstellungen und Generator.
## 1.24.0 Responsive UI, FLUX-Auftragsarchiv & zentrale Bildergalerie
- Listing-Seite auf schmalen Breiten von einer starren Mindestbreite auf echte responsive Kartenzeilen umgestellt.
- Responsive Härtung für Filter, Batch-Aktionen, FLUX-Job-Center, Formulare, Aktionsleisten und Medienverwaltung ergänzt.
- Hintergrundentfernung im Advanced Editor um eine regelbare Intensität von 0 bis 100 erweitert.
- FLUX-Aufträge können einzeln oder gesammelt archiviert und aus dem Archiv wiederhergestellt werden.
- Im FLUX-Archiv können einzelne, mehrere oder alle Aufträge endgültig gelöscht werden; erzeugte Bilder bleiben erhalten.
- Serverseitige Pagination und Seitengröße für aktive und archivierte FLUX-Aufträge ergänzt.
- Neuer Navigationsbereich „Bilder“ als zentrale Galerie für FLUX-, bearbeitete, AI- und Listing-Bilder.
- Galerie mit Raster-/Listenansicht, Suche, Quellenfiltern, Favoriten, Sortierung, Pagination, Mehrfachauswahl, ZIP-Download, Lightbox, Editor-Übergabe und geschützter Löschung aktiver Listing-Bilder.
- Vinted-Titelfeldschutz aus Vendoo Link 1.6.1 unverändert beibehalten.
## 1.23.2 Slice 31.2 Hotfix: FLUX-Layout, Editor-Werkzeuge & kompakte Aufträge
- „System & ComfyUI“ aus der angehefteten FLUX-Seitenspalte entfernt und direkt unter „Prompt & Auftrag“ eingeordnet.
- FLUX Job-Center als Ganzes ein- und ausklappbar gemacht.
- Einzelne FLUX-Aufträge kompakt auf- und zuklappbar; aktive Aufträge sind standardmäßig geöffnet, abgeschlossene kompakt geschlossen.
- „Alle einklappen“ ergänzt, damit lange Verläufe die Seite nicht unnötig vergrößern.
- Separate Buttons für Hintergrundentfernung und Wasserzeichen aus Generator und Bildleisten entfernt.
- Hintergrundentfernung in den Advanced Image Editor integriert und als nicht destruktive Bildversion gespeichert.
- Wasserzeichen mit eigenem Text, fünf Positionen und einstellbarer Deckkraft in den Advanced Image Editor integriert.
- Editor-Werkzeuge gelten einheitlich für Generator-, Listing- und FLUX-Bilder.
- Vendoo Link 1.6.1 und der Vinted-Titelfeldschutz bleiben unverändert erhalten.
## 1.23.1 Slice 31.1 Hotfix: Editor-Sichtbarkeit & Vinted-Feldschutz
- Advanced Image Editor erhält im Generator einen deutlich sichtbaren eigenen Einstieg.
- `app.js` und `style.css` werden versionsgebunden geladen; HTML/JS/CSS werden vom Vendoo-Server nicht mehr aus veraltetem Browser-Cache ausgeliefert.
- Der Windows-Starter öffnet Vendoo mit Build-Kennung.
- Vinted-Auto-Fill ordnet Felder nur noch über eindeutige Selektoren bzw. tatsächlich zugeordnete Labels zu.
- Zustands-, Marken-, Größen- und Farbauswahl dürfen das Titelfeld nicht mehr als Fallback verwenden.
- Vendoo Link auf Version 1.6.1 angehoben.
# Changelog
## 1.23.0 Slice 31: Advanced Image Editor
- Bestehenden einfachen Fotoeditor durch einen nicht destruktiven Produkt- und FLUX-Bildeditor ersetzt.
- Undo/Redo und eine vollständige Bearbeitungshistorie innerhalb der aktuellen Sitzung ergänzt.
- Persistente Bildversionen in `image_edit_versions` eingeführt; das Original bleibt unverändert und jederzeit wiederherstellbar.
- Vorher-/Nachher-Ansicht und Auswahl älterer Bearbeitungsversionen integriert.
- Freien Zuschnitt sowie 1:1, 4:5, 3:4, 16:9 und Original-Seitenverhältnis ergänzt.
- Drehen, horizontales/vertikales Spiegeln und stufenloses Begradigen umgesetzt.
- Belichtung, Helligkeit, Kontrast, Lichter, Schatten, Temperatur, Sättigung und Schärfe ergänzt.
- Export als JPEG, WebP oder PNG mit Qualitätsregler und Zielgröße umgesetzt.
- Bearbeitungen werden serverseitig mit `sharp` in voller Auflösung gerendert und immer als neue Datei gespeichert.
- Hintergrundentfernung, Inpainting, Outpainting und Maskeneditor bleiben bewusst außerhalb dieses Slices; es gibt keine Platzhalterbuttons.
## 1.22.0 Slice 30: FLUX Studio Pro
- Persistentes FLUX-Job-Center mit SQLite-Aufträgen und einzelnen Varianten eingeführt.
- 1, 2 oder 4 Varianten, eindeutige Seeds und reproduzierbarer Seed Lock ergänzt.
- „Ähnlich erneut erzeugen“, Favoriten und vollständige Prompt-/Parameterhistorie umgesetzt.
- Abbruch, Wiederholen, Queue-Bereinigung und Neustart-Wiederaufnahme ergänzt.
- ComfyUI-Warteschlange, Historie, System-, GPU- und VRAM-Daten angebunden.
- Fortschrittsanzeige des FLUX Studios auf reale Phasen ohne geschätzte Prozentwerte umgestellt.
- Freier FLUX-Promptworkflow bleibt ohne Produktreferenz und ohne `LoadImage`.
- FASHN VTON und Virtual Try-on bleiben vollständig entfernt.
## 1.21.0 Slice 29: FLUX Quality & Settings Tabs
- Einstellungsbereiche als horizontale Top-Tabs neu gestaltet.
- FLUX Studio mit Prompt-Check, lokalem Prompt-Assistenten und Qualitätsprofilen erweitert.
- FLUX.1-schnell standardmäßig auf vier Schritte optimiert; Detailprofil mit sechs Schritten.
- Negative Prompt im reinen FLUX-Promptmodus entfernt.
- Startprofile Auto, Schnell, Ausgewogen und Wenig VRAM ergänzt.
- ComfyUI-Start verwendet je nach Profil Cache-/VRAM- und optionale Fast-Flags.
- Laufzeit und final strukturierter Prompt werden je Bild gespeichert.
- Vorschau und Bearbeitungsaktionen visuell aufgewertet.
## 1.20.1 FLUX Runtime Startdiagnose und Health-Check
- FLUX/ComfyUI-Start wartet jetzt bis zu 180 Sekunden auf den echten `/system_stats`-Health-Check statt nach 2,55 Sekunden vorschnell „gestoppt“ zu melden.
- Eigene Runtime-Statusdatei mit PID, Laufzeit, Startphase sowie bereinigten stdout-/stderr-Auszügen.
- ANSI-Farbcodes werden aus den angezeigten Runtime-Logs entfernt.
- Prozessabbruch während des Starts wird sofort erkannt und mit den letzten relevanten Logzeilen gemeldet.
- Das reine Vendoo-FLUX-Studio startet ComfyUI ohne benutzerdefinierte Nodes; der verwendete Workflow benötigt ausschließlich eingebaute Standard-Nodes.
- Start- und Stopp-Skripte liegen jetzt als feste Paketdateien vor und werden beim Drüberkopieren sofort aktualisiert.
- FLUX Studio und Einstellungen zeigen während des Starts laufend „Wird gestartet“ statt einen falschen Stoppstatus.
## 1.20.0 FASHN/VTO entfernt und eigenständiges FLUX Studio
- FASHN VTON, Modelbibliothek, lokale VTO-Dienste, API-Routen, UI, Installationsskripte und Einstellungen vollständig aus dem aktiven Produkt entfernt.
- Bestehende VTO-Runtime, Autostarts, Logs und alte VTO-Einstellungen werden beim ersten Setup-Lauf entfernt; eigene alte Modelbilder werden nach `uploads/ai-generated/legacy-models` gesichert.
- Neuer Hauptmenüpunkt **FLUX Studio** mit freiem Prompt, Stil, Format, Seed und Schritten.
- Live-Status und Start/Stopp-Steuerung für das lokale ComfyUI/FLUX.
- Vorschau, Download, Bildbibliothek, Löschen und Übernahme in den Listing-Generator.
- Nachträglicher Bildeditor für Zuschneiden, Drehen, Spiegeln, Helligkeit, Kontrast und Sättigung. Bearbeitungen werden als neue Version gespeichert.
- Neue Tabelle `flux_images`; aufgegebene VTO-Tabelle und `ai_vto_*`-Einstellungen werden aus bestehenden Datenbanken entfernt.
- FLUX bleibt ein reiner Prompt-Bildgenerator; Ghost Mannequin und Flatlay bleiben als separate Produktbild-Werkzeuge bestehen.
## [1.15.0] - 2026-07-07
### Neu
- Komplett neu strukturierte Einstellungszentrale mit Bereichen für Allgemein, AI & APIs, Marktplätze und lokales FLUX.
- Großer FLUX-Live-Status mit klarer Anzeige für Aktiv, Gestoppt, Deaktiviert und Nicht installiert.
- Lokales FLUX kann direkt aktiviert, deaktiviert, gestartet, gestoppt, repariert, aktualisiert und sicher deinstalliert werden.
- Sichere FLUX-Deinstallation entfernt ComfyUI und das Modell, behält standardmäßig aber die Installationsarchive für eine schnelle Neuinstallation.
- Einstellbare Produktreferenz-Treue für AI-Model-Fotos.
- Neuer Geschwindigkeitsmodus mit 768 × 768 Pixeln als Standard; 1024 × 1024 bleibt als Qualitätsoption verfügbar.
### Behoben
- Produktfotos werden bei lokalem FLUX jetzt tatsächlich an ComfyUI übertragen und als Image-to-Image-Referenz in den Workflow eingebunden.
- Hoodie, Farbe, Kapuze, Reißverschluss, Aufdrucke, Logos und Schnitt werden im Prompt zusätzlich als verbindliche Produktmerkmale geschützt.
- AI-Bildjobs aktualisieren ihren Fortschritt jetzt während Vorbereitung, Upload, Rendering, Sicherheitsprüfung und Speicherung statt dauerhaft bei 10 % zu stehen.
- Alte oder beschädigte Installationsstatusdateien können nicht mehr zu `unknown · Bereitschaft 100%` führen, wenn die reale Installation vollständig vorhanden ist.
- Der konfigurierte Installationspfad `local-ai/comfyui` wird korrekt auf den enthaltenen Portable-Ordner aufgelöst.
### Technik
- Neue ComfyUI-Referenzpipeline: UploadImage → LoadImage → ImageScale → VAEEncode → KSampler.
- Neue Datenbankspalte `ai_model_jobs.progress_message` als additive Migration.
- BOM-sicheres Lesen des FLUX-Installationsstatus.
- Neuer PowerShell-5.1-kompatibler Uninstaller `scripts/uninstall-local-flux.ps1`.
## [1.14.6] - 2026-07-07
### Behoben
- Lokaler FLUX-Workflow wird unter Windows PowerShell 5.1 als UTF-8 ohne BOM geschrieben.
- Bereits vorhandene Workflow-Dateien mit UTF-8-BOM werden beim Einlesen robust bereinigt.
- `Unexpected token '' ... is not valid JSON` bei der lokalen AI-Bildgenerierung behoben.
- Installer-Status-JSON wird ebenfalls ohne BOM geschrieben, damit Node.js und andere JSON-Parser es zuverlässig lesen können.
# 1.14.5 Slice 22.3 PowerShell 5.1 Parser Fix
- Behebt den PowerShell-5.1-Parserfehler `InvalidVariableReferenceWithDrive` im sichtbaren FLUX-Downloadstatus.
- Ersetzt die beiden ungültigen Zeichenfolgen `$Label:` durch die eindeutig begrenzte Form `${Label}:`.
- Der bestehende Resume-Download, die `.part`-Datei und der automatische Setup-Ablauf bleiben unverändert erhalten.
- Keine Datenbank-, Konfigurations-, Upload- oder Listing-Daten werden verändert.
# 1.14.4 Slice 22.2 Download Recovery
- Fortsetzbarer HTTP-Streaming-Download statt BITS/Invoke-WebRequest.
- Sichtbare Fortschrittsanzeige mit Prozent, MB, Geschwindigkeit und Restzeit.
- Automatische Wiederaufnahme über setup.bat.
# Changelog
## Slice 22.1 / 1.14.3 Setup-integrated PowerShell 5.1 recovery
- Fixed the false 7-Zip failure when `Process.ExitCode` is empty under Windows PowerShell 5.1 despite a successful extraction.
- A missing exit code is accepted only when `Everything is Ok` is present, stderr is empty and the extracted result passes file-count and size checks.
- Complete `local-ai\extract-temp` results are reused instead of being deleted and extracted again.
- `setup.bat` now starts with UTF-8 console handling, `-NoProfile` and explicit exit-code reporting.
- Normal `setup.bat` startup detects the exact confirmed Slice-22 false-failure state and offers automatic continuation.
- Automatic continuation installs ComfyUI, downloads the FLUX.1-schnell model and starts the local image server without a separate patch command.
- Installer intent flags are persisted in `install-state.json` for future resumable runs.
- No reset, database change or feature removal is performed.
## Slice 22 / 1.14.2 7-Zip extraction watchdog and real FLUX install telemetry
- Replaced the blocking 7-Zip invocation with a supervised process and explicit path quoting.
- Live extraction status now includes elapsed time, extracted file count, extracted MB, process ID and heartbeat.
- Added 7-Zip stdout/stderr logs and a visible UI panel for extraction details.
- Detects stalled installers instead of showing an endless running state.
- Reuses complete downloads and safely restarts only the failed extraction/install step.
- Handles nested ComfyUI portable archive layouts more robustly.
- Setup status now shows live extraction counters and stale heartbeat detection.
## Slice 21 FLUX Installer 7-Zip Hotfix & Detailed Status
- Fixed PowerShell 5.1 scalar-string bug where a single 7-Zip path such as `C:\Program Files\7-Zip\7z.exe` was indexed as the single character `C`.
- 7-Zip discovery now uses a real string list, refreshes PATH after winget installation and validates the final executable path.
- Partial ComfyUI and FLUX downloads now use `.part` files and are validated before being promoted to complete files.
- BITS downloads now report actual transfer percentage, bytes transferred and total bytes into `local-ai/install-state.json`.
- Installer failures preserve the last real progress value and include source position plus resumable-state metadata.
- Settings UI now shows detailed checks for 7-Zip, archive, Python runtime, ComfyUI, FLUX model, workflow and start/stop scripts.
- Install log tail, error details, readiness score and a resume-aware install button were added.
- Setup option 8 now prints phase, progress, file checks, runtime reachability and recent install log lines.
## Slice 20 Vollautomatischer lokaler FLUX-Installer
- Automatischer Download der aktuellen offiziellen ComfyUI-Windows-Portable-Version über die GitHub-Releases-API
- GPU-Erkennung für NVIDIA, AMD, Intel und CPU-Fallback
- Automatische 7-Zip-Installation über winget, falls erforderlich
- Optionaler Download von FLUX.1-schnell FP8 aus dem offiziellen Comfy-Org-Hugging-Face-Repository
- Fortschritts- und Statusdatei unter `local-ai/install-state.json`
- Fortsetzbare Downloads über BITS mit WebRequest-Fallback
- Sichere Startparameter: Bindung an `127.0.0.1`, kein Browser-Autostart, eigener Port 8188
- Optionale Windows-Autostart-Aufgabe `Vendoo Local FLUX`
- UI-Aktionen für Installieren, Aktualisieren, Starten, Stoppen und Status prüfen
- Setup-Menü schützt weiterhin vor versehentlicher Neuinstallation von Vendoo und erkennt vorhandene FLUX-Installationen
- Provider-Reihenfolge im Auto-Modus: lokal FLUX → OpenRouter Free → OpenAI
## Slice 19 Local FLUX / ComfyUI Bootstrap, safer setup install flow
- Setup hardened: Install checks whether Vendoo is already installed and suggests Start / Update / Repair instead of blindly reinstalling.
- New setup options: local FLUX / ComfyUI bootstrap and status checks.
- New local image provider architecture for AI model photos: Auto now supports Local FLUX -> OpenRouter Free -> OpenAI.
- New server routes for local image status, bootstrap install and token regeneration.
- Settings UI expanded with local FLUX URL, token, workflow path and install path.
- Added local workflow bootstrap template and helper scripts under `scripts/` and `local-ai/workflows/`.
## Vendoo 1.12.0 OpenRouter Diagnostics & Mobile Mediathek
- Mobiler QR-Upload besitzt jetzt getrennte Aktionen für **Kamera** und **Mediathek**
- Mehrfachauswahl aus der Smartphone-Mediathek ohne `capture`-Zwang
- HEIC/HEIF werden beim mobilen Upload nach Möglichkeit automatisch in JPG konvertiert
- OpenRouter-Free-Erkennung bewertet nur bildrelevante Preisfelder
- OpenRouter versucht je Modell mehrere kompatible Chat-Request-Varianten und danach die Images API
- Referenzbilder werden nur an Modelle gesendet, die Bildinput unterstützen
- Klare Diagnose, wenn aktuell **0 kostenlose Bildmodelle** verfügbar sind
- Bei Fehlern werden weiterhin alle passenden Free-Modelle nacheinander versucht; Auto fällt anschließend auf OpenAI zurück
## Vendoo 1.11.0 LAN QR Upload, OpenRouter Fallback & Mobile Nav Fix
- QR-Handy-Upload verwendet automatisch eine erreichbare LAN-IP statt localhost
- Vendoo lauscht für lokale Netzwerkzugriffe auf `0.0.0.0` und zeigt erkannte LAN-Adressen beim Start an
- Neue Einstellung für `PUBLIC_BASE_URL` inklusive automatischer LAN-IP-Erkennung
- OpenRouter probiert bei Fehlern automatisch weitere passende Free-Bildmodelle und danach im Auto-Modus OpenAI
- OpenRouter-Bildgenerierung unterstützt Chat-Completions und Images-API als zweistufigen Fallback
- Mobile Navigation vollständig gehärtet: Overlay, Close-Button, Fokus, Escape, Scroll-Lock und responsive Labels
## Vendoo 1.10.0 AI Jobs, 13 Varianten & History
- AI-Bildgenerierung läuft jetzt über eine Job-Queue statt nur synchron
- Mindestanzahl auf **1 Bild** gesenkt, Maximum bleibt **3 Bilder**
- Neue Modi: **Model**, **Ghost Mannequin**, **Flatlay**
- Listing-Editor zeigt jetzt eine **AI-Bild-Historie** zum schnellen Übernehmen früherer Generierungen
- Settings erweitert um Standard-Modus für AI-Bilder
## Vendoo 1.9.0 AI Provider Settings Center
- Neuer Settings-Bereich für AI-Model-Fotos mit Provider-Steuerung
- Admin kann jetzt `auto`, `openrouter` oder `openai` für Bildgenerierung wählen
- OpenRouter-Free-Modelle können direkt aus der UI geladen und geprüft werden
- Safety-Flags, Standard-Preset, Variantenanzahl und Fallback-Modell sind in der UI konfigurierbar
## Vendoo 1.8.0 OpenRouter Free Image Discovery
- AI-Model-Fotos unterstützen jetzt einen Provider-Modus `auto`
- OpenRouter Free-Bildmodelle werden dynamisch über die Models-API abgefragt und bei Verfügbarkeit bevorzugt genutzt
- Fallback auf OpenAI (`gpt-image-1` oder konfiguriertes Modell), wenn keine freien OpenRouter-Modelle verfügbar sind
- Neue API-Route für verfügbare OpenRouter-Bildmodelle sowie Persistenz von Provider und Modell je Generierung
## Vendoo 1.7.0 AI-Model-Fotos & Safety Layer
- Neuer sicherer AI-Model-Foto-Workflow für Kleidung ohne Person auf dem Originalfoto
- 23 KI-generierte Zusatzbilder mit fiktiven erwachsenen Models in Studio-, Indoor- oder Outdoor-Looks
- Precheck & Output-Safety: blockiert Unterwäsche, Bademode, transparente Erotik-Looks, Kinderkleidung und Quellen mit Personen
- Neue Backend-Routen, Datenbanktabellen und Listing-Integration für Generator und Detailansicht
# Changelog
## [Unreleased]
## [1.6.2] - 2026-07-07
### Branding
- neues Vendoo-Hauptlogo in die App-Sidebar integriert
- neues Branding auf Login und mobilem QR-Fotoupload integriert
- vollständiges Favicon-Paket mit ICO, PNG, Apple Touch Icon und Webmanifest eingebunden
- mobile App-Icon-Größen von 16 bis 512 Pixel ergänzt
- Chrome-, Edge- und Firefox-Erweiterungen auf die neue Vendoo-Icon-Familie aktualisiert
- Vinted Assistant und minimierter Assistant verwenden das neue Logo
## [1.6.1] - 2026-07-07
### Verbessert
- Dashboard ist jetzt der erste Menüpunkt und die Standard-Startseite.
- Dashboard-KPI-Karten verwenden eine fließende Auto-Fit-Struktur statt starrer Sechserspalten.
- Sparklines besitzen eine reservierte Diagrammfläche und überlagern keine Texte mehr.
- Umsatzdiagramme werden bei Größenänderungen automatisch neu berechnet.
- Dashboard-Charts passen sich an Notebook-, Tablet- und Mobilbreiten an.
- Studio-Flow-Karten verwenden proportionale Bildflächen mit vollständiger `contain`-Darstellung.
- Produktbilder werden nicht mehr abgeschnitten und erhalten einen sauberen Fehlerzustand.
- Ready-Karten verteilen sich automatisch auf die verfügbare Breite.
## [1.6.0] - 2026-07-07
### Hinzugefügt
- neuer Sidebar-Menüpunkt **Dashboard** mit interaktiven Kennzahlen, Umsatzverlauf, Plattform- und Kategorieauswertung
- Dashboard-Bereiche für Fokusaufgaben, Top Seller, Aktivität, Benachrichtigungen, AI-Qualität und Systemstatus
- Fotoarchiv-Endpunkt: mehrere Fotos werden serverseitig als gültiges ZIP erzeugt
- Foto-Download im Generator und vollständigen Listing-Editor
### Geändert
- Studio Flow vollständig neu strukturiert: Bereit, Geplant, Veröffentlicht, Verkauft und Benötigt Aufmerksamkeit
- die fachlich unpassenden sichtbaren Stufen „Neu erfasst“ und „AI-Prüfung“ wurden entfernt
- Studio Flow zeigt nur priorisierte Artikel statt einer überfüllten Spaltenwand
- geplante Listings, Probleme und Aktivitäten sind in klar getrennten Arbeitsbereichen organisiert
- Dashboard und Studio Flow für Notebook, iPad, Tablet und Smartphone neu priorisiert
### Behoben
- Publish-Center lädt Listings beim ersten Öffnen mit Wiederholungslogik und verhindert veraltete parallele Renderings
- Publish-Ladefehler zeigt jetzt eine konkrete Wiederholen-Aktion statt einer Sackgasse
- bei einem Foto erfolgt ein normaler Download, bei mehreren Fotos automatisch ein ZIP-Download
## [1.5.0] - 2026-07-07
### Hinzugefügt
- Browser-Erweiterungen in getrennten Ordnern für Chrome, Edge und Firefox
- vollständiger Design-Relaunch von Popup und Vinted Assistant
- neues Vendoo-Link-Icon in 16, 32, 48 und 128 Pixel
- QR-basierter Handy-Fotoupload für Generator und Listing-Editor
- sichere, zeitlich begrenzte Mobile-Upload-Sitzungen
- responsive Layout-Gates für Desktop, Notebook, iPad und Smartphone
- umschaltbare Plattformvorschau und HTML-Codeansicht
### Verbessert
- Produktbilder der Extension werden vollständig dargestellt
- CSRF-Unterstützung für schreibende Extension-Requests
- öffentliche Serveradresse statt festem localhost für Extension-Bilder
- Plattformvorschau und HTML-Code sind in Generator und Listing-Editor als Umschalter zusammengeführt
- Layouts für Desktop, Notebook, iPad und Smartphone neu priorisiert
- freigegebene Extension- und Icon-Mockups als verbindliche Designreferenz archiviert
### Behoben
- Studio Flow: „Prüfen & bearbeiten“ wechselt jetzt zuverlässig zur sichtbaren Listing-Detailansicht.
- Detailaufrufe aus Attention Queue und anderen Bereichen verwenden denselben sicheren Navigationspfad.
- Ungültige Listing-IDs werden abgefangen und als Hinweis angezeigt.
- Windows-Installer behandelt npm `ENOTEMPTY`/`EPERM` robust, bereinigt unvollstaendige `node_modules`, protokolliert npm-Ausgaben und wiederholt die Installation einmal.
- Installation nutzt mit vorhandenem Lockfile reproduzierbar `npm ci` statt eines stillen `npm install`.
### Geplant
- Lager, Vorlagen, Einstellungen und Admin gemäß Design-Freeze
- Docker- und Online-Readiness
## [1.4.0-full-listing-editor] - 2026-07-07
### Hinzugefügt
- Listings lassen sich jetzt vollständig in einem eigenen Arbeitsbereich bearbeiten
- Fotoverwaltung mit Hinzufügen, Entfernen, Cover-Auswahl, Drag-to-Sort und vollständigem Bildeditor ergänzt
- WYSIWYG-Editor und HTML-Code sind im Listing-Editor bidirektional und live synchronisiert
- Generator zeigt HTML-Code und Plattformvorschau gleichzeitig; Änderungen werden ohne Umschalten übernommen
- Plattform-HTML wird während der Bearbeitung live neu gerendert
- neue Datenbankspalte `description_html` mit Migration und Rückwärtskompatibilität
- neuer API-Endpunkt `POST /api/html-render` für nicht persistierende Live-Vorschauen
- Editor-HTML und vollständiges Plattform-HTML können getrennt kopiert werden
### Sicherheit
- Rich-Text-HTML wird client- und serverseitig auf eine begrenzte Tag- und Attributmenge reduziert
- Plattformvorschauen laufen in sandboxed iframes
- Listing-Updates verwenden jetzt eine feste Feld-Allowlist statt beliebiger SQL-Spaltennamen
### Behoben
- `photos` werden bei Listing-Updates korrekt als JSON gespeichert
- Bildbearbeitung funktioniert nun auch für bereits gespeicherte Listings
- formatierte Beschreibungen bleiben nach Speichern und erneutem Öffnen erhalten
## [1.3.0-publish-center] - 2026-07-07
### Geändert
- Publish-Bereich als durchgängiges operatives Publish-Center neu aufgebaut
- Smart Copy, Direkt-Publishing, eBay Queue und Zeitplanung in einer gemeinsamen Oberfläche zusammengeführt
- bildorientierte Listing-Auswahl mit Suche, Plattform-/Statusfilter, Sortierung und Mehrfachauswahl ergänzt
- internes Workspace-Modell statt separater Queue- und Smart-Copy-Modale eingeführt
- direkte Listing-Bearbeitung vor Etsy-/eBay-Veröffentlichung integriert
- Publish-Bereitschaft, Pflichtfelder, Integrationsstatus und Fotoprüfung sichtbar gemacht
- Queue-Status, Schnellaktionen und Publish-Aktivität in einer festen Statusleiste gebündelt
- eBay-Fehler, Wiederholungen und geplante Veröffentlichungen inline bedienbar gemacht
- responsive Darstellung und Dark Mode für das komplette Publish-Center ergänzt
### Behoben
- Batch-Smart-Copy öffnete denselben Vorgang teilweise doppelt
- nicht passende Etsy-Batch-Auswahl wird jetzt gefiltert statt blind veröffentlicht
- Produktbilder im Publish-Center werden vollständig und ohne Beschnitt dargestellt
- Queue- und Planungsaktionen bleiben im Vendoo-Kontext und verlieren nicht den aktuellen Arbeitsstand
## [1.2.0-listing-studio] - 2026-07-07
### Geändert
- Listing-Generator als dreigeteilter Studio-Arbeitsplatz neu aufgebaut
- Foto-Cover, Sortierung, Qualitätscheck und vollständige Bildanpassung integriert
- AI-Konfiguration mit Plattform, Provider, Modell, Sprache, Varianten und Vorlagen neu strukturiert
- artikelspezifische Verkäufernotizen mit Zeichenzähler ergänzt
- Ergebnisbereich mit Live-Zählern, Qualitätswert, Attributen, Gebühren und HTML-Vorschau modernisiert
- responsive Darstellung und Dark Mode für den Generator vollständig ergänzt
### API
- `POST /api/generate` akzeptiert `template_id` und `seller_notes`
- globale Hinweise, Vorlagenhinweise und Artikelhinweise werden dedupliziert kombiniert
- Standard-Tags aus Vorlagen werden mit AI-Tags zusammengeführt
### Behoben
- Upload begrenzt neue Bilder clientseitig auf die verbleibenden Plätze bis maximal zehn
- Upload-Fehler werden mit HTTP-Status und Servermeldung korrekt angezeigt
- Dateinamen in Vorschaubildern werden URL-sicher ausgegeben
## [1.0.1-ui-foundation.1] - 2026-07-07
### Hinzugefügt
- zentrale Vendoo-Design-Tokens für Light und Dark Mode
- neue kompakte App-Shell und Hauptnavigation
- Command-Search-Einstieg mit `Ctrl/⌘ + K`
- neue Startseite `Studio Flow`
- Flow-Stufen: Neu erfasst, AI-Prüfung, Bereit, Geplant, Veröffentlicht, Verkauft
- Attention Queue und Activity Stream
- kontextueller Artikel-Inspector
- neuer Endpunkt `GET /api/dashboard/workflow`
- Dokumentation `docs/UI_FOUNDATION_2026.md`
- sicherer `.gitignore`
### Sicherheit
- `.env`, SQLite-Laufzeitdateien, Uploads und `node_modules` aus dem Übergabepaket entfernt
- keine produktiven Zugangsdaten in der bereinigten Version
## [1.1.1-ui-polish] - 2026-07-07
### Geändert
- Etiketten und Artikeldatenblätter öffnen jetzt im internen Vendoo Print Studio statt in einem neuen Browserfenster
- maßstabsgetreue A4-Vorschau mit zwei Etikettenformaten, Exemplaren und Preisoption
- Druck erfolgt im aktuellen Vendoo-Fenster über den normalen Systemdruckdialog
- Studio-Flow-Produktbilder verwenden vollständige automatische Anpassung (`object-fit: contain`)
- Inspector- und Attention-Bilder werden ebenfalls ohne Beschnitt dargestellt
- Vinted-Extension auf die freigegebene Vendoo-Designsprache 2026 umgestellt
- Extension-Popup und eingeblendetes Vinted-Panel modernisiert
- Produktbilder der Extension werden sicher über den Background-Service-Worker als Data-URL geladen
- Pfade von Upload-Bildern werden korrekt URL-codiert und Bildfehler erhalten einen sichtbaren Zustand
- fehlerhaft doppelt codierte deutsche Texte in der Extension repariert
### Behoben
- Produktvorschaubilder in der Vinted-Extension wurden durch Seiten-CSP/Mixed-Content-Konstellationen teilweise nicht angezeigt
- große oder hochformatige Produktbilder wurden im Studio Flow abgeschnitten
## [1.1.0-ui-listings] - 2026-07-07
### Geändert
- Listings-/Historie-Seite vollständig an die freigegebene Vendoo-Designrichtung 2026 angepasst
- neue Filterleiste mit Suche, Plattform, Status und Zeitraum
- benutzerdefinierbare sichtbare Tabellenspalten mit lokaler Speicherung
- dichte, bildorientierte Listing-Tabelle mit SKU, Plattform, AI-Provider, Preis, Status, Lagerort und Publish-Status
- neue Batch-Aktionsleiste für Publish, Nachbearbeitung, Preis, Status, Duplizieren, Etiketten und Löschen
- moderne Seitennavigation und Seitengrößensteuerung
- neue Exportauswahl für CSV und JSON
- verbesserter leerer Zustand und responsive Darstellung
- bestehende CRUD-, Export-, Druck-, Status- und Papierkorb-Funktionen erhalten
## [1.6.1] - 2026-07-07
### Geändert
- Vendoo Assistant für Chrome, Edge und Firefox vollständig verdichtet und visuell neu strukturiert.
- Queue-Karten zeigen Bild, Status, SKU, Preis und direkte Aktionen ohne große Leerflächen.
- „Nur ausfüllen“ ist jetzt die primäre und sichere Einzelaktion.
- Daten können in Vinted eingetragen werden, ohne automatisch einen Entwurf anzulegen oder zu veröffentlichen.
- „Daten + Bilder ausfüllen“ überträgt Bilder und Felder, führt aber keinen Abschluss aus.
- Entwurf und Veröffentlichung liegen bewusst in einem getrennten, aufklappbaren Abschlussbereich.
- Popup öffnet Vinted mit einem vorgemerkten Listing und füllt es nach dem Laden aus.
- Extension-Version auf 1.4.0 angehoben.
@@ -1,96 +0,0 @@
# Vendoo — Projekt-Kontext
Du arbeitest am Projekt "Vendoo" — ein lokaler Multi-Plattform Listing-Generator mit AI, Lagerverwaltung und Publishing-System.
Lies zuerst `FEATURES.md` im Projektroot — das ist die vollstaendige Feature-Dokumentation mit Tech Stack, Projektstruktur, DB-Schema, allen 80+ API-Endpunkten und 17 Feature-Beschreibungen.
## Tech Stack
- **Backend:** Node.js + Express (ESM, `"type": "module"`)
- **Frontend:** Vanilla HTML/CSS/JS — kein Framework, kein Build-Step, kein TypeScript
- **Datenbank:** SQLite via `better-sqlite3` (WAL-Modus)
- **AI:** Anthropic Claude, OpenAI, OpenRouter, Ollama (lokal)
- **Bilder:** `sharp` (Resize, BG-Remove, Watermark)
- **Rich-Text:** Quill Editor
- **E-Mail:** Nodemailer (SMTP)
- **Extension:** Chrome Manifest v3
## Dateistruktur (wo was hingehoert)
| Aenderung | Datei(en) |
|---|---|
| Neue API-Route | `server.mjs` — Route hinzufuegen + Import erweitern |
| Neue DB-Funktion | `lib/db.mjs` — Funktion exportieren |
| Neue DB-Spalte | `lib/db.mjs` — MIGRATIONS-Array erweitern (try/catch ALTER TABLE Pattern) |
| Neues UI-Tab | `public/index.html` (Sidebar-Button + Section), `public/app.js` (TAB_TITLES + switchToTab + Logik), `public/style.css` |
| Neuer AI-Provider | `lib/ai-*.mjs` + `lib/ai-router.mjs` erweitern |
| Neue Plattform | `platforms/*.mjs` + `lib/categories.mjs` + `lib/fees.mjs` + `lib/html-templates.mjs` |
| Styling | `public/style.css` — CSS Custom Properties fuer Theming |
## Konventionen
- **Sprache:** UI ist komplett Deutsch
- **SKU-Format:** `VD-XXXX` (auto-generiert, 4-stellig aufsteigend)
- **Navigation:** Sidebar mit `data-tab` Attributen, Tab-Inhalte als `<section id="..." class="tab-content">`
- **Topbar-Titel:** `TAB_TITLES` Map in `app.js` muss fuer neue Tabs erweitert werden
- **Dark Mode:** CSS-Variablen unter `[data-theme="dark"]`, niemals hardcoded Farben
- **Auth:** Session-basiert, Rollen `admin`/`editor`, CSRF-Token bei state-changing Requests
- **DB-Migrationen:** Neue Spalten als Eintrag in `MIGRATIONS`-Array (Zeile ~17-21 in db.mjs):
```js
const MIGRATIONS = [
['spaltenname', 'TEXT'], // oder 'REAL', "TEXT DEFAULT 'wert'"
];
// Wird automatisch per try/catch ALTER TABLE ausgefuehrt
```
- **API-Pattern:** REST, JSON-Body, Fehler als `{ error: 'message' }`
- **Frontend-API-Aufrufe:** `api(method, path, body)` Helper in app.js (fuegt Auth + CSRF automatisch hinzu)
- **Toast-Benachrichtigungen:** `toast('Nachricht')` in app.js
- **Quill-Editor:** `initQuill(selector, placeholder)` — gibt Editor-Instanz zurueck
## Server starten
```bash
npm install # Dependencies installieren
npm run dev # Dev-Server mit --watch (Port 8124)
npm start # Produktiv-Server
```
Oder: `setup.bat` fuer gefuehrte Installation.
## Wichtige Dateien nach Groesse
| Datei | Zeilen | Inhalt |
|---|---|---|
| `public/app.js` | ~3240 | Gesamte Frontend-Logik |
| `server.mjs` | ~1250 | Alle API-Routen + Middleware |
| `public/style.css` | ~1200 | Komplettes Styling + Dark Mode + Responsive |
| `public/index.html` | ~845 | HTML-Struktur (Sidebar, Tabs, Modals, Forms) |
| `lib/db.mjs` | ~390 | Datenbank-Zugriff (alle CRUD-Funktionen) |
| `lib/categories.mjs` | ~360 | Kategorie-Baeume pro Plattform |
| `lib/auth.mjs` | ~290 | Auth-System (Users, Sessions, Audit) |
| `lib/ebay-api.mjs` | ~270 | eBay REST API + OAuth2 |
| `lib/mailer.mjs` | ~210 | SMTP E-Mail-Versand |
| `lib/etsy-api.mjs` | ~185 | Etsy REST API v3 + OAuth2 PKCE |
| `extension/content.js` | ~1170 | Chrome Extension Content Script |
## Aktueller UI-Stand
- Version `1.3.0`
- UI 2026 Slice 05: Publish-Center
- Smart Copy, direkte Veröffentlichung, eBay Queue und Scheduling arbeiten in einer gemeinsamen Oberfläche.
- Interne Publish-Arbeitsschritte dürfen keine separaten Browserfenster oder redundanten Modale öffnen.
## Bildarchitektur ab 1.23.0
- FLUX/ComfyUI ist der einzige lokale generative Bilddienst.
- Das FLUX Studio arbeitet textbasiert und getrennt von Produktbild-Werkzeugen.
- Keine VTO-, Python-, Torch- oder ONNX-Laufzeit wieder einführen, solange kein neuer ausdrücklicher Architekturentscheid dokumentiert ist.
- FLUX-Studio-Aufträge und Varianten sind in `flux_prompt_jobs` und `flux_prompt_job_variants` persistent.
- Fortschritt im FLUX Studio wird als reale Phase dargestellt; keine aus Laufzeit geschätzten Prozentwerte ergänzen.
- ComfyUI-Prompt-IDs müssen für Abbruch, Historie und Neustart-Wiederaufnahme erhalten bleiben.
- Der Advanced Image Editor arbeitet nicht destruktiv: Originaldateien niemals überschreiben oder löschen.
- Jede gespeicherte Bearbeitung muss eine neue Datei und einen Eintrag in `image_edit_versions` erzeugen.
- Bildpfade müssen strikt auf `uploads/` begrenzt und gegen Traversal geschützt bleiben.
- Hintergrundentfernung, Inpainting, Outpainting und Maskeneditor nicht als Platzhalter ergänzen; diese Funktionen benötigen eigene spätere Slices.
@@ -1,33 +0,0 @@
# syntax=docker/dockerfile:1.7
FROM node:22-bookworm-slim AS dependencies
WORKDIR /app
RUN apt-get update \
&& apt-get install -y --no-install-recommends python3 make g++ ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY package.json package-lock.json .npmrc ./
RUN npm ci --omit=dev --no-audit --no-fund \
&& npm cache clean --force
FROM node:22-bookworm-slim AS runtime
ENV NODE_ENV=production \
PORT=8124 \
VENDOO_BIND_HOST=0.0.0.0 \
VENDOO_DATA_DIR=/app/data \
VENDOO_DB_PATH=/app/data/db/vendoo.db \
VENDOO_UPLOADS_DIR=/app/data/uploads \
VENDOO_BACKUP_DIR=/app/data/backups \
VENDOO_OPERATIONS_DIR=/app/data/operations \
VENDOO_LOG_DIR=/app/data/logs \
VENDOO_CONFIG_PATH=/app/data/config/vendoo.env
WORKDIR /app
COPY --from=dependencies --chown=node:node /app/node_modules ./node_modules
COPY --chown=node:node . .
RUN mkdir -p /app/data/db /app/data/uploads /app/data/backups /app/data/operations /app/data/logs /app/data/config \
&& chown -R node:node /app/data \
&& chmod +x /app/scripts/docker-entrypoint.sh
USER node
EXPOSE 8124
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
CMD node -e "fetch('http://127.0.0.1:8124/readyz').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"
ENTRYPOINT ["/app/scripts/docker-entrypoint.sh"]
CMD ["node", "bootstrap.mjs"]
@@ -1,397 +0,0 @@
f344f75df655bc133e6c4abb2d215b2234fb22a4bb155c217317c36ee4f0f8fb .dockerignore
e5cc1e85c80485ceda76fd6c69330e085ccc7bc1248be810fe4243712cf39118 .env.example
58e3f4b76cc9398f32dcd5481b2080e7e5ba322aca04b8b8374446299c5d7dd6 .github/CODEOWNERS
5bd335eb750d084ca12b6a3b3f35d0cd7bc454ba24ed280187c66acf75eaf396 .github/dependabot.yml
f65684e98b01d0e0b6bfe1284b5de3354559e4cd51e634fe9e9e2e5473b890e5 .github/pull_request_template.md
6641ae3ef2b49dbf2d0f76fe1d0c8a76554fb154a0c82738c49848f466cc776b .github/workflows/ci.yml
e3efad6c06973cb58958c9d4f8cdb8adec61907acb82804c06b6b6a0aaa1d160 .github/workflows/release.yml
9e7decb6c419fc032644ad361043e69770104ea5904bfcce4942f9416787d975 .gitignore
9bfa732952ad571d06527b32d96d79133fc23fa607df00de440b2802f543608c .npmrc
3ae3049aaf372d61f1d39f53c97f697128b352aff1726c6e3b99feb86223a264 CHANGELOG.md
61823fc9fdc036170cce6edeecbb612b442d1c65fc9f7a7eaba47e5016316ee5 CLAUDE.md
2e0077cd6dd83d3a07fcef25b7e37ab5fc056dbe1ca034b33d55135234045882 Dockerfile
3a72c2ba86fca6655af49a47e853a335532586dbf5ea620d909570ec7d76cb02 FEATURES.md
7f78a0d512de717ba76c9a5e3e1bd2e52db9edf146e8eeb7297458fde5d92afa GitHub-Deploy-Assistent.bat
302ab1609d08b3059ba6563b676c64f0709651f2e3c531857bfca3840c535a79 MockupDesign/AdminDashboard.png
49f7625a1299a16576feabfd7824ec3511391bd9b7c53a1fba9232da7e8bd6c6 MockupDesign/ChatGPT Image 7. Juli 2026, 10_05_19 (1).png
7b8cc9c5db8718b0b653ec6aa9d2a8bfa1bba03810248c3ba17745b6f15cc412 MockupDesign/Dashboard.png
4e3e797ed5d3ed0b60d00d8e567fbe51543c08578b858ef71e77b274ae449fd0 MockupDesign/Einstellungen.png
c78fd6f673c0e59789ea313396b12c2f21f75a2ee6c7ad2de81a6b89f6d90588 MockupDesign/ExtensionDesignMockup.png
ed20bc04cab8e85245a855810a61b736a682f972eb85e23340edc9b558851a93 MockupDesign/Heute StudioFlow.png
1ad88f45f377ab9b3f35f96a0ceaaa7f75cb0a996e83370d76c54f527392a08d MockupDesign/IconLogoMockup.png
0e8b4a31d075f1f83ea62b5eeeb53e89859e395a696deb43155932a23e7cef86 MockupDesign/Lager.png
b1c62e118d9be316274e966c558cdcccdd41afb3a9f05a60ec1e4a3433d2ca0c MockupDesign/Listings.png
a52983b9ea2bf920d115485d10bc30226da88bc5cba8b00bebf801b21c096346 MockupDesign/Publish.png
8c8bf278d0c6725e1dbb97b3c3d0c36a9bfc0753c3c86433fdc294bec70dbc0e MockupDesign/Startseite.png
62f14221b1d71c9e631efdadd221397ff657adae4b737df52c8bff1610b90999 MockupDesign/Vorlagen.png
13ab5b29d5bb22a7c48e7a782a901681de0a5ea314fb243d863c063f6a39d3bb README.md
3cc4cbb3f67a7cff7fc1892dd1b9d695dd1b6ed1596ce454b2edbd11ecf76faf SECURITY.md
2851c914a1b50a036cb265ddd32e5545cc7e8e34ba9d682445926acc23eb8f28 THIRD_PARTY_NOTICES.md
4c424ef64a09639953388bd2e749d45e9a0d3d533c8b6fce547292237a0a48f9 app/architecture-boundaries.json
a6bdb9b6fdc97a0b2bbc052bd242a9885a75bcc46ee4f0414d8b7e215b6940de app/contracts/module.schema.json
918cddaee5056cadddcff39d86744cf68ab409fbff46aa54b6b465b72b199c01 app/core/security/secret-contract.mjs
7f38b3ac792e61e030c9f69355e2378f8f61e8e61c7b29c82cd0fa7ec930cfec app/core/themes/theme-contract.mjs
d84a573699e413e0a0803459e0d05c5c4e6e35d3499eb634f95302d151e75c4b app/kernel/errors.mjs
a34333cbc784d39b39a8071a437972c6175c551104dc2d82fc4c0e0506b18259 app/kernel/event-bus.mjs
0e8f691f96e1ef0a7a86d32cae7b7e1db04325fe94a32b8c1f484a5b6950f3b4 app/kernel/feature-flags.mjs
e2e0b74fa04efa787c0494c0d4b755b9445c6f38dc8d9cd7ec206683b0fb1da8 app/kernel/input-schema.mjs
a0223a00691908862aaf1fd9383b6d86d67f26325c509280b8c2daa5cfcee28e app/kernel/lifecycle.mjs
ba1f4f799a508ff113738cce7ac9f5af27739cb60d7f04d7a6c5878de3c5b7f4 app/kernel/module-contract.mjs
1baa99ffd80fffcfed69f21a5db8911500f35c0bd9df23cd02a7fb3b563266df app/kernel/module-registry.mjs
99931e7923b879bd68ceea3cb400ad041f3353e5c341e8a5643fe77f662ac213 app/kernel/platform-kernel.mjs
7944f68d995a5d70273f8a985973f668fc62a414d85636d92f3774e34d39a37f app/kernel/policy-engine.mjs
7547f4cae608feed54669fe94cc787ba2a06baad3c9c969d072fd11cca34288c app/kernel/route-registry.mjs
0bb099111f7cf49780389d0b078083756a448b663661ee22475d84d38a5f9719 app/modules/ai/module.json
83ad66e0eba88246d292c96fb1ec02b9c59ed15614bbbf4a4a989787fe51e2d3 app/modules/auth/module.json
dd28d6157d97aa812894a2db96c02f78200565e5adaf5913f92b1fcde759a705 app/modules/catalog.mjs
083db2c78089db389e51e743078c847f1067f3d1a39081080c601d31556f15fd app/modules/flux-studio/module.json
82b31b548c603cdc4e21b50707fd3d21114b85ef1f61db607c881f9ac1809132 app/modules/listings/module.json
6453b41f4074b37c7f7a2c30aa8a0eba8c4233f8d474251919094ed0c15fe38d app/modules/media/module.json
9723a9b12a9b472b2ed8c4635cdce663b2f0f65643d8ae0b6219715d853f740d app/modules/operations/module.json
b71c0f607bbba70b4485fcce883a7d2ab4a533a6dc203eb7de616aa4d8bae435 app/modules/publishing/module.json
61aa66129d18e2c5e6c2e7319de836a4713fde1ddcc31c6a5ca56c22d22d9b48 app/modules/quality/module.json
747febc12aec7d81ccfdf6e9ea7158655ef5fdc536c519ce447de329314612a8 app/modules/security/index.mjs
700be862cd70be6947919c1e1f0e25e7e88c313b1fcdddc104d54d88a74edbb2 app/modules/security/module.json
452a5262c418b393bdd8754fe90f9ea14edf61338f8dcfd6438f0852920f608c app/modules/system/module.json
92d968c993ee5a2afc14df557b7cba552cae9a41722989007eb0b784514333ff app/modules/themes/index.mjs
1e062db871f9bf13b487c972f6cd4dd9cfe1b3046cd9b53ed43e0a0babc9d285 app/modules/themes/migrations/001_theme_profiles.sql
2af572390890e4d793aea9c1356c835917655c225a7848325d5a7c5ae3c08a09 app/modules/themes/module.json
3c3dc5974976672cd0e9141867a8a1d78a0dfaa54582bafb8f360bea571bf11a app/modules/themes/repository.mjs
4e2c348a184384739408894f26b02c56c6bfd4dd531eebb9c67d2fb7fbad3009 app/modules/themes/service.mjs
11b4a1bc94b68998a3a2a8bec766bc56c7ff829939d914b0ce896f963feb10ed app/modules/users/module.json
c197ce417fbce6dab1d8ee157b0a105a099dd2021ece4dac3891d0b2022a0d58 bootstrap.mjs
4a3273ec603224a70ceb81c0d5ed6617c3ba2d3111342b4e646a79752f4b3f87 compose.bind-mounts.example.yaml
66d2e8a35289748f472d3ca2d703fe878f616b22ba30b1344251f78af07e3ecf compose.vps.yaml
69b9d6721198f5a93840ee4fb6ece45caf2898f036c3f9bba9aa05f0f4199964 compose.yaml
6323f984f1e04ab135356a14ec151941638041f6b305ed68772d5e1812972075 db/schema.sql
49690c4e4c8e84de8eb40ffe79823493b7be20fe46fa2ad9e6544f7f0afbfd2c deploy/Caddyfile
cc794bca282d79a27d860d0bfef4641769f4e9f31172778a1d9d8205558d948e docs/ABNAHMEBERICHT_1_32_0.md
de0d86f806a70195050613f5b56f6c4da1ee2eff02a9a991b6aacee229c46ca5 docs/ABNAHMEBERICHT_1_33_0.md
947745174897470de0bebf4f7c2b29a0c0ef3f1a762f277374c2614d9e3dec4f docs/ABNAHMEBERICHT_1_34_0.md
26c87fa38f804749a9363812127dc33ef69e201e4ef9b59206f6fe6e15c845b0 docs/ABNAHMEBERICHT_1_34_1.md
f792d366c13c5a4a9b4e8d4054e26190d9c327a7a770005d74bbe2b31bb84ab3 docs/ABNAHMEBERICHT_1_34_2.md
bc638fd21222ada7b15e40adff80a318aebec58139978109cbfd30040815a8d4 docs/ABNAHMEBERICHT_1_34_3.md
c0ae5c4176ba6f7510be047d4feaf383cd646152131003ebccc6bfbf8c8056f5 docs/ABNAHMEBERICHT_1_35_0.md
c050c8e11f2bdb0a742851423dcff864bafba9cc839c52b2f8d48b75f7b18633 docs/ABNAHMEBERICHT_1_36_0.md
1f3e96ba13844a3f1cefecca99b3d6313aebf86faae914897db0404ea031c491 docs/ABNAHMEBERICHT_1_37_0.md
67a1be91b0c2d2797716f785f2f770c881cf88d7fd617722468df8d949d0638a docs/AUDIT_1_31_0_IST_UND_LUECKENANALYSE.md
2acba8fcc5da42e5a808925a86628bc0c6fc817ddb082b0ead3857c6a43460f1 docs/BRANDING.md
f23c643236c84b0e3715620598f358065748b6d090229003e23df8ad9320b54e docs/FULL_LISTING_EDITOR_2026.md
ba9a9b93622fadc399cd9067d80b4ea339193eb19825106264a3b86b7128d107 docs/GENERATOR_STUDIO_2026.md
54f45ae5c2f12b6314b3f1bc3e59e753c64ca7cfe39644725d765e9f02f637ef docs/GITHUB_DEPLOYMENT_1_34_0.md
5a25e952d7d79b562bc19c990451830ea2ac3e730c9af399425ea18ffb8fd61d docs/GITHUB_IMPORT_STATUS.md
65d19c1576f4a6011008a7e447a3530222517752fb59ebc5bbb506b791e32605 docs/HOTFIX_1_23_1_EDITOR_CACHE_VINTED_FIELDS.md
c9c8f934a0c4192dae29df913588188aab1321364d1c46b9c66da5c754e9df41 docs/HOTFIX_1_23_2_FLUX_EDITOR_JOB_COLLAPSE.md
2306ff399000c07a9d7e260a58d92c748fa3219922a4dda25f6b2121a1ad2dbc docs/HOTFIX_STUDIO_FLOW_DETAIL.md
0584257245a29de62a6374eb8b114bd19fc6a36306ed990d820ed2062514d6a6 docs/INSTALLATION_1_32_0_WINDOWS_DOCKER_NAS.md
7c1afdefd1e3a75a5d6b49aedae80e266bab4e91cbfc657fb862ddfd737dc792 docs/INSTALLATION_1_33_0_MULTIPLATFORM.md
1475e484cccb0db67e02abbb05f8b8e676c85536ec4f5bda7dd99d4563fbc049 docs/INSTALLATION_1_34_0_ZERO_EDIT.md
1df2aed413865c03e541e66249c1df3eed6d3c3aea9f0ffdeaee40453665df14 docs/LISTINGS_UI_2026.md
4f74fef6877126d2579356b9731955e29f05ea8b55b59abb91569e47730a1c3f docs/PUBLISH_CENTER_2026.md
bae236366d6d2cb0139e4dbf8baf099599bbff27aacc9eeeba20fdff644f5fb0 docs/RELEASE_1_24_0_RESPONSIVE_MEDIA_FLUX_ARCHIVE.md
5223408e51f35ba5f6ce86155544311dd13f60522a6d482f372d64788ab466ac docs/RELEASE_1_24_0_VERIFICATION.json
b66524ffd19976f650c6b26b299898b182355950f545c131de16c89fcffe0ebe docs/RELEASE_1_25_0_RESPONSIVE_GALLERY_SMARTCOPY_PROMPTLAB.md
1c5ebf1a496c9571fe9d941793371f9f0be89d85a587c8fa9532f9b25bba92bc docs/RELEASE_1_25_0_VERIFICATION.json
1eef86e13d9429701e9d60894f36fe0eba82c974565b1a6687ed157ca6da680e docs/RELEASE_1_25_1_ADAPTIVE_GALLERY.md
14475ae4169f4bde4a5b7ae5512867f972ede69dcb621d7cc6a208d4fdc6a331 docs/RELEASE_1_25_1_VERIFICATION.json
f02b80194f434dd3d82b5c4c111e8cae65f1f053a267cec2793a1ff551daff9a docs/RELEASE_1_26_0_ARTIKEL_EXTENSIONS_PUBLISH_GALLERY.md
570522a6513134227122da1b5f2f56a421c62d3b0b5adba703872e9026fa2b58 docs/RELEASE_1_26_0_VERIFICATION.json
4cfc47f35765259cbd6a841f51a85fa86600991d1ca545b10756f15b6d332f7f docs/RELEASE_1_26_1_STABILITY_GATE.md
9646b913994b1bf8ce03eab57e7a6a87061540e44fdde63ad5b7eee93ca9f475 docs/RELEASE_1_26_1_VERIFICATION.json
7c6c3a2e4ce478f47e540a34a3505dbbe11b8f2175d0b274bec7643457997140 docs/RELEASE_1_30_0_OPERATIONS_CENTER.md
6f9c206869ba94c461b1d9f8e40847792b8891bb27809a0c6fa3d1d68a4e8598 docs/RELEASE_1_30_0_VERIFICATION.json
5da62e06d768ce832d18fb3ecb3ccca2f051a6218d2d3cb492d1e5aebbcccb52 docs/RELEASE_1_31_0_MULTIUSER_SECURITY.md
6288a31dfa61f71d13f79d40ab64bb7ca475de07ada154c002cd4b0d44a284dc docs/RELEASE_1_31_0_VERIFICATION.json
4ee88ff8c3c655cb31bc18192a37ffdd0eedf8e26039b252094d5ce169c1883c docs/RELEASE_1_32_0_DOCKER_NAS_PRODUCTION.md
628d4d1a6c7d837a0c8c22958253193642ddfeaab5f425f418f9f32b46e84340 docs/RELEASE_1_32_0_VERIFICATION.json
624919ea60969079f767068771800dbc04ea7a87eb1a53d7f0497447492c25cb docs/RELEASE_1_33_0_MULTIPLATFORM_DEPLOYMENT_FLUX_ADMIN.md
3f9ae39792bec600ddd534284ae62cb2b4f9db01fb54c09cee8ae161551caa2a docs/RELEASE_1_34_0_GITHUB_ZERO_EDIT.md
c724b699894d5ec3c050af0253c6de0c645a789219a344ad7ffe31e330d9921b docs/RELEASE_1_34_0_VERIFICATION.json
7caa9e7b1e51af362332e9c50165b60c54c9219c7384c8313d3735c387df1c01 docs/RELEASE_1_34_1_GIT_SAFETY_WINDOWS_HOTFIX.md
ac834ee57ab6bd8fe3dd0238837193e66e01d7e78590a289347b002591da3fb4 docs/RELEASE_1_34_1_VERIFICATION.json
51057d17e2636ef1bdfc6751dfad29ebd34fbe7f41b870f8f2f756a5c97d1c4a docs/RELEASE_1_34_2_GIT_SAFETY_DIAGNOSTICS_STAGING_FILTER.md
4c2c141ffc85b1d7517672abf2b28bb19fe4769505c0eb4d37e22bae06826cb3 docs/RELEASE_1_34_2_VERIFICATION.json
d55eaec79e10800a930fa030367ffa34037755e5757bc532e72d25711c5ca09a docs/RELEASE_1_34_3_UPDATE_ARCHIVE_EXCLUSION.md
4bb731af51e786a4827ec48bc7c4d4843c287456aedc09d8b74aa0eed3c0ec16 docs/RELEASE_1_34_3_VERIFICATION.json
e7bb3bb950e3c5303746f43139ca8f7c985d2d73896b44f5b707dd46a9152529 docs/RELEASE_1_35_0_PLATFORM_KERNEL.md
33eb9f0059a2ddc4b4debe5bf733720f2a5bb22f2710bab0a0cc9ac1b898ff11 docs/RELEASE_1_35_0_VERIFICATION.json
5a9fcfa0ea6e9c5c13f6d943e1de4d31c21e21fcff9186e8a714d7a16ed1c18f docs/RELEASE_1_36_0_SECURE_THEME_MANAGER.md
2dfe705857424865f101e861f4e633c8a7fb3c0e8dab874cb6620fd09b1ca902 docs/RELEASE_1_36_0_VERIFICATION.json
527806c00fb51334457726a9a7e9f6fc13f4dacd985fa2d2b97d5eb21c543853 docs/RELEASE_1_37_0_SECURITY_SECRETS_OBSERVABILITY.md
fe5756f788b2ab131f0832504d90d46d1ed744bfe470fd040803985234afa3cf docs/SLICE_02_ACCEPTANCE.md
05614ecf41becc399acfa6a3b2f681f37a8c80f5ce0130b98c578b2c8c60713c docs/SLICE_05_ACCEPTANCE.md
0838bcc6464a6beff39f0b4b056e513c1a390193521d9a8fc5d440d38034e9d0 docs/SLICE_06_ACCEPTANCE.md
ae0f7c6f6e614ec77e362db1076288596ec48d11b78f33f26908fbc40ae5dd18 docs/SLICE_07_EXTENSIONS_RESPONSIVE_MOBILE.md
b561983736639a08146d3642b718651907853d589ee32e5f421fc090f2c75a20 docs/SLICE_08_EXTENSION_AUTOFILL_UX.md
c5bf7a0c9f787f100e422d0deb27bffc2c8c86b0e7c1ce1f35d2de8d7d8ea774 docs/SLICE_11_DASHBOARD_RESPONSIVE_HOTFIX.md
876675bc3015838f568a6970ef6c01c9fcafe1d8d138c4379bc0f2ee1fd7445b docs/SLICE_22_1_SETUP_AUTO_RECOVERY.md
223f50d05096b3bfa3ac3a9f0880a2055fc2029b7d70fabd086612c3348cb34a docs/SLICE_22_2_DOWNLOAD_RECOVERY.md
95e1d560378120d7ccb0f363720ba832505631aa65616abd4df01baba5ecc269 docs/SLICE_22_3_POWERSHELL_51_PARSER_FIX.md
88f5a2d021874764b6a7f56c690a1e2112155b83cdf0d4d964b2c6e00ca756de docs/SLICE_22_3_SHA256.json
791a5d30f0d6ff9664722a2d00dff0db0bbdf2207e83ab391a40d6c4ab913bba docs/SLICE_22_4_SHA256.json
d14c938c6c9397290f654406d4b995b63db0f22586e78fc97fb5fef575748807 docs/SLICE_22_4_UTF8_BOM_FIX.md
f00c325ec3c879b47908dd5410cc943febb923200e9b9bd7d18197b1570a26fe docs/SLICE_22_4_VERIFICATION.json
e140f3ee3298b3894126e37900b04ff1073ed400e6414e35897815b3f674d93e docs/SLICE_23_FLUX_REFERENCE_PROGRESS_SETTINGS.md
b4b01b9f3751940d184d6fff269108798c7ec62ca7796b923cf82abbc142ff3b docs/SLICE_23_VERIFICATION.json
05e3fcf5aa9a0d8d53175a3d24c5feb36e55f73edfeadf05384e87a5de73353a docs/SLICE_28_1_FLUX_RUNTIME_HEALTHCHECK.md
43d867bb8b455f7450e5146648b28c759e50ebab45855d75a36dbc9f91d3f654 docs/SLICE_28_FLUX_STUDIO_VTO_CLEANUP.md
0bdbeed4b57767427afbebeddc30ea58a211f851663939d6301af38820cf098f docs/SLICE_28_VERIFICATION.json
1e20fd1abea3ce61f7f9cc88c6e8e4ddb0fe3513c5600e41b8f7c3f8d38e3ae9 docs/SLICE_29_FLUX_QUALITY_SETTINGS_TABS.md
1df7305e6a43212a582d5f83630e0ba04fbdd3da0d673d9dcb8f1c5f7ca37731 docs/SLICE_29_VERIFICATION.json
07d1ad0c19567cbdb05623567816f1506197a31e86fbcd1742f4ffa300335ae4 docs/SLICE_30_FLUX_STUDIO_PRO.md
008237388c4816d3cd67f3f0abfd0512f4ebf2dce75ab6790de41b0481ae1d97 docs/SLICE_30_VERIFICATION.json
db1674505e2ca7eb36c8752ea9b2d6fe2f2c12a5e6a1584e2722e20445b05e34 docs/SLICE_31_ADVANCED_IMAGE_EDITOR.md
3133a06e68cd98e615797665956f1bc401c0427045298b46c48ca590be3ef9da docs/SLICE_31_VERIFICATION.json
d425fc1724ac55853bf3433348486de8f8aab111f53fefee3c532beb1deb82af docs/SLICE_32_BATCH_IMAGE_FACTORY.md
0a8917412d000168956f7ac55e60ab79b54a8834deef0386a681bb8f920514cd docs/SLICE_32_VERIFICATION.json
25ff8492360d473e99c75c308be5f75cf84e0c11574d42aa6553d44f8bb35582 docs/SLICE_33_ARTICLE_QUALITY_CENTER.md
1d5411f69c62222d3155f0e89f2b4b5a3effe317ea1e59347efa7730a8e1b0e9 docs/SLICE_33_VERIFICATION.json
1161decfabd73c40ff1d2ffbc7d1b9b5168a8fb5fa392187c1b431e9a7f3a78f docs/SLICE_34_PUBLISHING_HARDENING.md
aa7ebc90470071566749c61b0dece4169f87666dcca4b88922f7fbafcfdd5a84 docs/SLICE_34_VERIFICATION.json
4b66a14b4515e38477f10325ab9d03d9782ad0d426845aefe2d508986ed2cd81 docs/UI_FOUNDATION_2026.md
5e655fcf3bb1182f8850b4104b56697ea952b01d2698af6d3d40b05e338b3506 docs/UI_UX_FIXES_SLICE_03.md
e5f065ba8d516a5ebd47e7e6859d0aab40ef69797413e358d969ef27c454fcdd docs/architecture/DESIGN_SYSTEM_1_35_0.md
cc0edf92756a51414563b4407dedb21d1e3b36682f4bfbbc334aeb33a22ae1b4 docs/architecture/MIGRATION_ROADMAP_1_35_0.md
eb47b055dd336e8360ec7c4712dee4ae37f109f3820e3f185969e2327d790cf8 docs/architecture/MODULE_SYSTEM_1_35_0.md
d7773faac0e93510a5a51c91de997df03547b51f3124267dcf137d4e99299562 docs/architecture/SECURITY_ARCHITECTURE_1_35_0.md
58cd43938b06e29520b92516a1e816d17d2c08d4847b99c1ee700b2185f46f20 docs/architecture/SECURITY_FOUNDATION_1_37_0.md
771c4771c4d7335750c5a2d976c765b4ed66ed936d8550d7af69de14a16705bb docs/architecture/THEME_MANAGER_1_36_0.md
cc77a92ca268d3c444c6113a9cfaa38d3c805a579f6b1b21b7dd43a6ada58551 docs/superpowers/specs/2026-07-06-autolister-features-design.md
c7db96df5fed3c8336062204322d62b4870f5c8ab1d30ea48cc6e7e38ed3513b extension/README.txt
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e extension/background.js
b86f00c7afa1dc921dd66f5cfea8c817eebc8876b9daca6a55dfd03680156c79 extension/content.css
8ee8d1a94bbf83e5d09aee3c7d8c4ea5f216b2a51e73b6dbc74f7e6b99017a1c extension/content.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf extension/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b extension/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 extension/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 extension/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 extension/icon.svg
c2fdc0530c71ef400fe9d52aed914f65d331b0d89dfae7ef1d156d54d1a22a6b extension/manifest.json
e61fd8e1264995fd633bd76e71329813dd02f361286329832a18dfd5a8bdd372 extension/popup.css
bdf5b794473cae818789cf95a28a9c9a9d50f81529d72fdf45a536247a783922 extension/popup.html
d7893cfdd686d4a6a1bea333468d4ba72cfff0e7166687181a2d37ba1faf3332 extension/popup.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 extension/vinted-categories.js
48b5f9f4ecc1c1c42f37321e9bb2fc857c646b9c16c34520fc7d4ca59a1036ac extensions/README.md
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e extensions/background.js
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e extensions/chrome/background.js
c5a0ca59a8858e9bd484d1e5fb7a2aca72db092fb062674f531bb76f5a0c952e extensions/chrome/content.css
22bd64723d279a6229bccba2a4cec56f1ae83f4cd5628bd1a1841930b0f442f6 extensions/chrome/content.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf extensions/chrome/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b extensions/chrome/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 extensions/chrome/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 extensions/chrome/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 extensions/chrome/icon.svg
c2fdc0530c71ef400fe9d52aed914f65d331b0d89dfae7ef1d156d54d1a22a6b extensions/chrome/manifest.json
e3a3863b58a571a0f0180bdd333f9389b918415b4ea96b70f3ab6d4105d95c50 extensions/chrome/popup.css
559dc70841ebb186ff96f9f2ba32ef26a3a7f8edd08363f09c0d7163049eae5a extensions/chrome/popup.html
2bf2d5ccf02622cf1d62fd553d21c0ef1b744616742e7962ac302c10d37426e2 extensions/chrome/popup.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 extensions/chrome/vinted-categories.js
c5a0ca59a8858e9bd484d1e5fb7a2aca72db092fb062674f531bb76f5a0c952e extensions/content.css
22bd64723d279a6229bccba2a4cec56f1ae83f4cd5628bd1a1841930b0f442f6 extensions/content.js
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e extensions/edge/background.js
c5a0ca59a8858e9bd484d1e5fb7a2aca72db092fb062674f531bb76f5a0c952e extensions/edge/content.css
22bd64723d279a6229bccba2a4cec56f1ae83f4cd5628bd1a1841930b0f442f6 extensions/edge/content.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf extensions/edge/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b extensions/edge/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 extensions/edge/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 extensions/edge/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 extensions/edge/icon.svg
c2fdc0530c71ef400fe9d52aed914f65d331b0d89dfae7ef1d156d54d1a22a6b extensions/edge/manifest.json
e3a3863b58a571a0f0180bdd333f9389b918415b4ea96b70f3ab6d4105d95c50 extensions/edge/popup.css
559dc70841ebb186ff96f9f2ba32ef26a3a7f8edd08363f09c0d7163049eae5a extensions/edge/popup.html
2bf2d5ccf02622cf1d62fd553d21c0ef1b744616742e7962ac302c10d37426e2 extensions/edge/popup.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 extensions/edge/vinted-categories.js
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e extensions/firefox/background.js
c5a0ca59a8858e9bd484d1e5fb7a2aca72db092fb062674f531bb76f5a0c952e extensions/firefox/content.css
22bd64723d279a6229bccba2a4cec56f1ae83f4cd5628bd1a1841930b0f442f6 extensions/firefox/content.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf extensions/firefox/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b extensions/firefox/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 extensions/firefox/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 extensions/firefox/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 extensions/firefox/icon.svg
1954ca9f34b3afe109935173f685482f06bb685a9b8f0d4c344f0c6133ccfaaf extensions/firefox/manifest.json
e3a3863b58a571a0f0180bdd333f9389b918415b4ea96b70f3ab6d4105d95c50 extensions/firefox/popup.css
559dc70841ebb186ff96f9f2ba32ef26a3a7f8edd08363f09c0d7163049eae5a extensions/firefox/popup.html
2bf2d5ccf02622cf1d62fd553d21c0ef1b744616742e7962ac302c10d37426e2 extensions/firefox/popup.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 extensions/firefox/vinted-categories.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf extensions/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b extensions/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 extensions/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 extensions/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 extensions/icon.svg
c2fdc0530c71ef400fe9d52aed914f65d331b0d89dfae7ef1d156d54d1a22a6b extensions/manifest.chromium.json
1954ca9f34b3afe109935173f685482f06bb685a9b8f0d4c344f0c6133ccfaaf extensions/manifest.firefox.json
e4ea31f91a4c8df18901bfc77fc351a8808d19d690243b80bc4faa140e18f851 extensions/packages/vendoo-link-chrome-1.9.0.zip
e4ea31f91a4c8df18901bfc77fc351a8808d19d690243b80bc4faa140e18f851 extensions/packages/vendoo-link-edge-1.9.0.zip
74c219587cf0f827a1a1e2b8adacac55477be717fd4ae80e2ae027a9ffb0744d extensions/packages/vendoo-link-firefox-1.9.0.zip
9e828844f41154c87ccfc5d8f3a19476396e2782fbd0f956465b42fb508cb098 extensions/packages/vendoo-link-safari-1.9.0.zip
e3a3863b58a571a0f0180bdd333f9389b918415b4ea96b70f3ab6d4105d95c50 extensions/popup.css
559dc70841ebb186ff96f9f2ba32ef26a3a7f8edd08363f09c0d7163049eae5a extensions/popup.html
2bf2d5ccf02622cf1d62fd553d21c0ef1b744616742e7962ac302c10d37426e2 extensions/popup.js
afd76deccd8bcf26d39f8c86deb1de578873ddd8b09ac18eebacae33169bb420 extensions/safari/README_SAFARI.md
0b2a03d06faae7aaebeee8ec9fe1864422c8651f17ae90b185fd31474ac5eeb0 extensions/safari/build-safari-extension.command
3873602c1529daad6647a7585c858d817821de0afbec93a26d1b3f5a7b9cb01e extensions/safari/web-extension/background.js
c5a0ca59a8858e9bd484d1e5fb7a2aca72db092fb062674f531bb76f5a0c952e extensions/safari/web-extension/content.css
22bd64723d279a6229bccba2a4cec56f1ae83f4cd5628bd1a1841930b0f442f6 extensions/safari/web-extension/content.js
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf extensions/safari/web-extension/icon-128.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b extensions/safari/web-extension/icon-16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 extensions/safari/web-extension/icon-32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 extensions/safari/web-extension/icon-48.png
5904aad2263358a5be638db435d5a0576b8c2bf21d1a20114636d65dbdbc07a8 extensions/safari/web-extension/icon.svg
772f1e2e33f4d6d882fa0af663e315fd3b8208141227bb5beb9baaf1f4e08397 extensions/safari/web-extension/manifest.json
e3a3863b58a571a0f0180bdd333f9389b918415b4ea96b70f3ab6d4105d95c50 extensions/safari/web-extension/popup.css
559dc70841ebb186ff96f9f2ba32ef26a3a7f8edd08363f09c0d7163049eae5a extensions/safari/web-extension/popup.html
2bf2d5ccf02622cf1d62fd553d21c0ef1b744616742e7962ac302c10d37426e2 extensions/safari/web-extension/popup.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 extensions/safari/web-extension/vinted-categories.js
273322e8dc29b0c6b639a6cc7e44a9570ceece09306fd46003b05a8fc86c88b7 extensions/vinted-categories.js
9a5bfcafdce53130d7bc36695090a8f87096b4ead9dd5ccc3d46d1d80c07a0fa lib/ai-claude.mjs
b53b7a8dea3bd46bee9c32e2ea840d618b5cb31cceba49937c057ec615fb87b5 lib/ai-flux-prompt-jobs.mjs
347778ce521a1919ec0679918171dc625d7f04d6dec26c8a4700e702bc78de67 lib/ai-local-images.mjs
aeb5103c0179232b9954b7854be8099cf4bb0f3ef1ee908eb5e4faf6a8f1205f lib/ai-local.mjs
cad43695655fc1c805815d9d694f23bd41124c1b78bb6493e7fea8893c464320 lib/ai-model-jobs.mjs
9f474f665d6d610fe00d9e707e85314a854abb906e31db2bb9a3a7c76785ff4f lib/ai-model-photos.mjs
3fb484456b9e6374f14b53a2276eea8533642b7c9073bb73a1bb0dbed7048bbd lib/ai-openai.mjs
581c10b8346d0aa10169ed23ed49c038951ecd5cac014722c1080bbd5aec1c5b lib/ai-openrouter.mjs
271696d7cbef3581b667a8ce3b07d0b17b1e8b467fbede4d8aa512ecc5225515 lib/ai-router.mjs
76a2f1fdf60053739d82962264219060807022dfc9a2b3a644946fddff02a8d9 lib/archive.mjs
ee6aa662a1875f9df8da1000804a6061f1a0f52c7a266df3d515cab4d410465b lib/auth.mjs
3e2b75c0758703e590233cbcc9b589e3177134accecf5ed921791891cbfc8522 lib/categories.mjs
86793fb57a1dad32f4d93e34c27ffe9e77a95785dd30b2b55ffb67d0ad5e14fb lib/config-store.mjs
8c203e70e9ab07b996d4a53031892bbf37b10efd024f9e0013266cf2af0244a4 lib/db.mjs
54722d3f76ad9ee4fbe731d3a65c2a03d343eb82d98f8ea5a5996b1bec24d57f lib/ebay-api.mjs
524f1b48d467998da819f0b947f2551ad45784e588eb442304c5f6e925dffaee lib/etsy-api.mjs
5b2c566ff14fa502ba2cd4d4c918fe238a8e93c3283d521144093a897f9d8018 lib/fees.mjs
7dcb2fb5606140afb7a019094d20ef88e9b4e2c70041f77b06d67d8992fd25ce lib/html-templates.mjs
844f0f8bc1de849bacc8df5d57006d5fc1100c706acc1140939a981dfdf2df4b lib/image-batch-jobs.mjs
5ca5fc65a7de7c27243646d291dc42c0b5267a47705a09b306cd2c2eae2a77c8 lib/image-editor.mjs
5e7aa66faddd3d19bc6ebb9ddc13abfc4ab4f17d8c51bb39b2c4e0279385d788 lib/images.mjs
606f4cb1013c711d971dd201ab06df84ecb128bf5d5277095ce2e2ea56029e45 lib/mailer.mjs
ad53b2b39f894a685f79e723b3f2b987fc9d9a3b75d39d0059ad225bc36c08cf lib/operations-center.mjs
78d30585aac7dc663e803a19927c89ab02414c0495d81df503e28f7bae58701a lib/publishing-jobs.mjs
3a728417dd668d60fd1526ec738cb9b302f86c01d62b2227f12b2e44b7d389c7 lib/quality-center.mjs
faa5d84ca6b26d1602e53a402de74a5c9e3f9ef9a72233159101f2b0bb0e499f lib/runtime-paths.mjs
d3d862ab32fd276ecffb54c0307976ca680135d92f24d024c95d365a50257643 lib/secret-store.mjs
cbd60791ee86fe09f07fc9ed85be3654f7aa5a310baafd9053440952619e2bc9 lib/security.mjs
2fd970a6a357a26211f0b9bcf432e59e79f73dc9a4cd35f88cca939655eefdff lib/structured-logger.mjs
ddb9c7677600795a4adf8a19a7525b7551455459d16eed4cdfbe751ef9ddf0eb lib/zip.mjs
2924f4e8abe5ebbd099fe1ceb2bc6ceb4bdda55fa3e57dd299cfc05d310a9246 local-ai/start-local-flux.ps1
7c6176d8311b1ba9d511beb40edd41b8248e61c298528bbec3f9ef1171856c05 local-ai/stop-local-flux.ps1
5f220a2dca02cc0764f6d0157677611b26c88860b48367eb661b6e47a1b92265 local-ai/workflows/vendoo_flux_schnell_api.json
c848163a1cf38336947778d73c3b7f4039771270a4cf974352b0ea85e7879415 package-lock.json
3d70a7f7d0d100d3ce336f130f1e7a7de3e2244dbf8fbcfd1d8e3f06d254b6da package.json
3da71dd28cb25c7c7317b9061855d40c6a3ab8bc39391963b49ee1e707f838e5 platforms/ebay-de.mjs
cc1ca2b4384c8c548bf755dc33101d248541bf893c3d5f35369961f904afcc00 platforms/ebay-ka.mjs
fa52b247dd758aeee06120499bd1ae6c53e9f460f8bd7762b8f06141b201e32b platforms/etsy.mjs
5c925e3934a4c9e2f26dc15b3449a249f5ce20ecebbd459b15365a34804824d6 platforms/vinted.mjs
a2ea3f5f56dba8bd4d23fa54a26fd941567b4febdd1ed1b4e9f5bcc1c9786e53 public/android-chrome-192x192.png
46ea6ba4ca6ca2352f37353b8bc4ca258935d29ecb8d3c9b133a48ea75c0c58f public/android-chrome-512x512.png
4177569df5648213a0f8d65a5c0a9ae2c4f07ce28974a318ac03cf8c1b4e4a9e public/app.js
e0e7b8ef01c36f0625b6157aa46bd69de05c17be0b054208fb635d6507b52154 public/apple-touch-icon.png
a2ea3f5f56dba8bd4d23fa54a26fd941567b4febdd1ed1b4e9f5bcc1c9786e53 public/brand/favicons/android-chrome-192x192.png
46ea6ba4ca6ca2352f37353b8bc4ca258935d29ecb8d3c9b133a48ea75c0c58f public/brand/favicons/android-chrome-512x512.png
e0e7b8ef01c36f0625b6157aa46bd69de05c17be0b054208fb635d6507b52154 public/brand/favicons/apple-touch-icon.png
a0f1e01de4e8215e690c1ce869fecaae9d7ba3cc95883340a53ff38f6be52ce0 public/brand/favicons/browserconfig.xml
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b public/brand/favicons/favicon-16x16.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 public/brand/favicons/favicon-32x32.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 public/brand/favicons/favicon-48x48.png
15bf8dd655b34a8015447e834d387af12685238ede598f5f0e7927eea2933483 public/brand/favicons/favicon.ico
2daa93cca0ad2c0cab90a9e8ad4ea0ae4b64feeb68c422954020d17e2376a381 public/brand/favicons/html-snippet.txt
3798313cc939d9fa582a92638356abfcfc8f8b4f143d9434b7012446195e6937 public/brand/favicons/mstile-150x150.png
c372675942caa5010340f21fe521adc72af537d909008731976820fd84604d42 public/brand/favicons/site.webmanifest
b2dc767e7a01395d23a7f3f5915324db1a7d1912bac60470d2f7c10815895173 public/brand/icons/vendoo-icon-120x120.png
409a96b169bc91efbcd7e923614a8cb30c6ca36cbd727f41e02c2ee4f89098cf public/brand/icons/vendoo-icon-128x128.png
d276f50b298e4dfcbba9147550463aee498531280399167d1e9774aa8e5f7e21 public/brand/icons/vendoo-icon-144x144.png
3798313cc939d9fa582a92638356abfcfc8f8b4f143d9434b7012446195e6937 public/brand/icons/vendoo-icon-152x152.png
47122dc91010721e2692d11986f0b91d9b76634130a95723e92b2a070268d16f public/brand/icons/vendoo-icon-167x167.png
8c031a533aeec86818d442ce96e859497817d16c2c9bf037c68955b90e8ced6b public/brand/icons/vendoo-icon-16x16.png
e0e7b8ef01c36f0625b6157aa46bd69de05c17be0b054208fb635d6507b52154 public/brand/icons/vendoo-icon-180x180.png
a2ea3f5f56dba8bd4d23fa54a26fd941567b4febdd1ed1b4e9f5bcc1c9786e53 public/brand/icons/vendoo-icon-192x192.png
3f2517cfd215cb624ed639d60b064dfa5e88ce71eb7bbebbbfaa70b3d62556db public/brand/icons/vendoo-icon-256x256.png
9963f60ab46d7f015a9400ee22e8e7a9fed31781a3907ef14b674d179d8f5f45 public/brand/icons/vendoo-icon-32x32.png
cae3eb737c8ad3a82a679b09d33d991b501bf482e0132e99aa1b8ad064e472b4 public/brand/icons/vendoo-icon-384x384.png
64d7b63beed9f972848daabc86484b5672b42ac7ed402a0d3effb47e200bf253 public/brand/icons/vendoo-icon-48x48.png
46ea6ba4ca6ca2352f37353b8bc4ca258935d29ecb8d3c9b133a48ea75c0c58f public/brand/icons/vendoo-icon-512x512.png
bc85af557be532dcce6beb82cf9bd61af683666b00fb61e4b2069f78e60a9a33 public/brand/icons/vendoo-icon-64x64.png
01d59b665bc90dddbd34221e3a2ec3af11bff6fb328aab2c9947c03d74b0465d public/brand/icons/vendoo-icon-72x72.png
ed3dfa59e989b154fac88a3c72ac840290ee3e1565d44aa75596bf0055c74020 public/brand/icons/vendoo-icon-96x96.png
46ea6ba4ca6ca2352f37353b8bc4ca258935d29ecb8d3c9b133a48ea75c0c58f public/brand/icons/vendoo-icon-original-1254.png
8fd9901e07dc9172d162706511ac8dcce220a4c907cb3efa9940c9c13fa32526 public/brand/logo/vendoo-logo-cropped.png
3f39371abd1efa6cc8366aac9a6d067f3339b8f2a2da77ab8a26c6bdcf8c4fce public/brand/logo/vendoo-logo-original.png
b56d07515f6220de7fd0cb149fed598a7361c985ae6ca7cb14329a99e8947aee public/brand/logo/vendoo-logo-transparent.png
e83921d2af9930ab27df1abe64374cb9311189bfaaa951068109177443571a07 public/brand/logo/vendoo-wordmark-transparent.png
1711a9387f2d6e75797b77c8daa92b94d7a15e128476e4b8aa9d54ccb0692a0e public/core/api-client.js
f30395399a5c6d7e0a884b22f28f7648e6343695cee9960d6ff13b34de7b48f1 public/core/frontend-module-registry.js
fb3dbcd03f7ed15b773b582c2a2b785c3040d3319aba5b7c682a7e74e1cf3b4e public/core/safe-dom.js
38aa57d13aeb3ab70babcb903bfee71e47d80932ed24a73267c13ff81c24e3ba public/design-system/theme-contract.json
308f1c0e2ed1de34aa11545a1a660aab02631e422d6c6945e3203d11666784fc public/design-system/theme-runtime.js
4d69e2cb6b7f9f63b54d708a5d8b1ebefcdcb9f88a977053db5031c05b098464 public/design-system/tokens/source.json
4a9e65edeaee3421edc3dd4831230062494f1a42f8495f4cb979fde8664d06c4 public/design-system/tokens.css
15bf8dd655b34a8015447e834d387af12685238ede598f5f0e7927eea2933483 public/favicon.ico
5157f9a0acad9e663d84e1b064a4b626ed61d08f3472ad058848a076bc7074b4 public/index.html
da7f1b6488e33c9ff94323d2da3bdcea91e386484c11e5202432e567721704b4 public/login.html
e37558ee9612a36db8a19999fbb320f1c249a8e155f94c83a82926bec920f989 public/login.js
59291f75eca405e3856bafea76cc601d681060eb6b36bf82a4be3c3ab7eac290 public/mobile-upload-expired.html
f046f166d89fc32774b87deb02e6d144fd2f40c0925aac67487e5b7c489a0ec1 public/mobile-upload.css
6152e4fe715efbf8fd6a7c4286f23172bc3cf15dde085e5e4f7389ad5e65ad73 public/mobile-upload.html
f13846801a8493aa43df6ec3d78b826b21b59e8f21d47735f68fd0b278e440c7 public/mobile-upload.js
01f2bd124257220005032bf234d122b9942fdd8fd57ed8195748b2fb1f5a5cfb public/modules/README.md
2d7a004db3e22b30ad3a682ba445bcee3fc1c5f0ed5e8fee45b5892c5b335e51 public/modules/theme-manager/theme-manager.css
0edc61f0c2bb604c3adc40813b18fe5ca8d9b846ec2a3d9f406ae26ae313d3ee public/modules/theme-manager/theme-manager.js
e0a6c981d4231eab26d981be62647d0e6f89e05e8371baad121348202ad54f49 public/style.css
ff525e0af963e6f54636cfdc1bd2d045aaf82e7b0199755eb5cdf4c52110be2e public/vendoo-icons.js
cc90bb9042d7f3c5b73a061c4621f36cf44c8841d35083c3033bae725d8525c0 scripts/docker-backup.sh
20e7590a7633b6c61086a5596d0bec1d343f0ff0eecc444ac932130ff363e258 scripts/docker-entrypoint.sh
50d93e7f9f71fa72071e5b2f3c63a548e4252c8096f6f8fa78342e5cf51db5c9 scripts/docker-restore.sh
9a692ace2e8f92ff245be890277a74541c252e295591818597b8cfe08b3176a1 scripts/github-deploy.ps1
00f950df71ddd4c5f62385529620cd85bfc73fb54e991489cedee05217ebe556 scripts/github-deploy.sh
0a9bafc79c1c5d59fb9b51ebc34c00eec4a4e9a5e873ce1818f50f3ab983da70 scripts/install-local-flux.ps1
2924f4e8abe5ebbd099fe1ceb2bc6ceb4bdda55fa3e57dd299cfc05d310a9246 scripts/runtime-start-local-flux.ps1
7c6176d8311b1ba9d511beb40edd41b8248e61c298528bbec3f9ef1171856c05 scripts/runtime-stop-local-flux.ps1
1a5736cf5fccc991df122163977c2eac80281bd99a54a5680b3d7eae99e4b79d scripts/start-local-flux.bat
3bf3aa74f5cc1f2946bb2da637eb30fe8daec783a32f9721ebb0468e20df90bd scripts/uninstall-local-flux.ps1
241b006d4066a68e330e26c8e38a041559b4e5c1368ad8cf3db5e2f63d6d8397 server.mjs
3c33e7042bf4e95fa56a5e163a42f156b7995e7d89fef9e8db7d48577037828f setup-gui.ps1
cf4519ce5adc01f05458e3286e86f3a419cceaff5fcdd869a1d07f1c1d1a0d8c setup.bat
9658fe68ddff2903505b92998a9e78385dc73dd269804dc5a7447099b8a0457f setup.ps1
24f9614b10f0a970f5233d9ac7083bca6c3d305b37ff29b57a5c21473b7f30a7 setup.sh
90485a16e3468cb9a6750646700fbb036cb9ac410e9b8bd5c582f7b923bf3c31 tools/build-release.mjs
ac8440bce2659a035302609722f1dfed5d125223376cd575ffc0636397c94b54 tools/generate-design-tokens.mjs
294659f2beb607540abbc3d6b4a1658525448a42f8880f2b282081a259c4e35b tools/prepare-git-staging.mjs
8f9ede5f112ee03323db3a6c73aee00b7037f5139dad241b11baf5f0e9cee4e0 tools/verify-config-store.mjs
5752f6edb956696781da8bddb1c1848d26941fbed5a524691653c84c88c34bff tools/verify-db-migrations.py
3745de55a110d8254983b096c6afab196ddaec7f1153cd2f34c1e480b15aa33e tools/verify-deployment-1.32.0.mjs
44f6b349b722e5a83d4725c4879fa1a9383f59ab5634c49d3d7d9d7aa0cd5e12 tools/verify-deployment-1.33.0.mjs
cbd91b45d97e11bd4f5ca2f9d2edf2b5931cb2aa336cb71afc30aad9cffbe1e0 tools/verify-deployment-1.34.0.mjs
01a43040a95cdac40703f49031acd9267cdba99d9027a51718f35ffb643237fc tools/verify-deployment-1.34.2.mjs
906767e574c06aedebb2d7797150bda2f1e4c4536e8f82f4c7de2e3cc8398c8e tools/verify-deployment-1.34.3.mjs
71d00227a59592cc0ad8ba321c63350ec25748ef965d8cd0eff1317738c7fba8 tools/verify-deployment-1.35.0.mjs
b65eec7fd54e1459b363d99d20f9438ae5bc4b518e775de8b97e33e89a382e42 tools/verify-deployment-1.36.0.mjs
22a5ba1951b2e8dbc924e60aaff8be7c41189ae7b30de9ecf50d0b741e84e13a tools/verify-deployment-1.37.0.mjs
1f052446f6c9627420afeb48aa09771b61f9e08ba573f6a0651b2843ef0b79f8 tools/verify-git-safety-regression.mjs
5bba3d7ae042b0bcf4eb56bacb3f6e41e1b0e00cadd7666505792ba6748cc987 tools/verify-git-safety.mjs
2f8d687319619240efe5849c276f7723e69755c66aa3b9609e41fdf0cda01e55 tools/verify-git-staging.mjs
1d4351e4a827e718766a1677ddfbc3771a91942d0d5a93753e39f1b99c68a4dd tools/verify-hotfix-1.23.2.mjs
44c95844422be3deaad6054ee3f0cced9c25986815d976e0c64b042d0c2c5e1e tools/verify-installer-shell.sh
cab03e98687af87f359f6424d440fc0b644da97b3c614509b8c7d008d4b18a8d tools/verify-platform-architecture-1.35.0.mjs
732bb15431746a829e45ae55c695360cbf1dd21d4fc3be26a98f35708d571e84 tools/verify-platform-architecture-1.36.0.mjs
ee8ae7bed4e93a2ef278662552a4ae5d751306aad7133a93f380bbf2a5d5a28c tools/verify-platform-architecture-1.37.0.mjs
36e35fedb08923c22fd8551389d33432b66dbd4215d95c594ef29bfc790c98e0 tools/verify-release-1.25.0.mjs
89621694b7bad18b6f3f1ac1956032f64112c40d3edc069ca581dc813d57d628 tools/verify-release-1.25.1-static.mjs
c908f5186cf2d71ef83d5e649327ae19965568933acfb32057ca00d29cf890bc tools/verify-release-1.25.1.mjs
e31a055d2ebb8e439f5b0e0235a71dacecb891e299377cfbbcfa8a32f53a85b0 tools/verify-release-1.26.0-static.mjs
7e107b5f9a1b4ee381ff31105feb6d38dda5c40e4afe105a955badc36e6b8d10 tools/verify-release-1.26.1-static.mjs
d9a75c45f40d857c84790d51dca2fd088c3851ca250405871a7e32773918c66e tools/verify-release-1.27.0.mjs
3989e3ec236c1aa4c387b26cc15e04cf200a018e29c095321acf826c6bae4d66 tools/verify-release-1.28.0.mjs
7d196d913a697248ab1233907fed56c10329cf201e3bdc173bca73cb02755369 tools/verify-release-1.29.0.mjs
3f30260dabbdf0fa7b042381cb9e24f840d0c3ddbc44fe309763789a7d14afb7 tools/verify-release-1.30.0.mjs
b1ceed5dfc17dbd3b038b7168e61076e4d39a0f1d67e2b87677a91c4dbb2daff tools/verify-release-1.31.0.mjs
a372258b97aa68d59a1fe0fd3f380d019c59412d5c408a6064f437d5cfc6e709 tools/verify-security-1.31.0.py
08820d9bb7be1dec496c04e9ea4a39b2ebb84d373a9481136610d16dea0edde3 tools/verify-security-foundation-1.37.0.mjs
31a120622ce8bb8451014f2662366f81abd28d0f3be59adfe35d17e0ada1838f tools/verify-slice30-mock.mjs
20957a4a038b9afdb01a8c98b881644daf793d2a6bb778a4c8e04780687d00e4 tools/verify-slice31-image-editor.mjs
21061ed5dc88feef48e80efffd9a1054d38598dce5a5d3f9f6bde39b539b83f0 tools/verify-slice32-batch.mjs
0f05b1ac3b686cf535bcfb3e6f6df24a29c3429ade1b3c666c1b99abb1a7311b tools/verify-slice32-image-render.mjs
c9aa6693aa93ff1f220a2ce3bc35ef714a0b18a53eae0f907879fc92c66c1e38 tools/verify-theme-manager-1.36.0.mjs
1e61c4b180aa09de3dae9e72aef313b09a6f422229f180984b69a8d226e7cd8d tools/verify-theme-manager-1.37.0.mjs
0f3f684019763a14f5fbaec42e42c680cf748d930d46cd607fc61eb413ca4553 tools/verify-ui-contracts-1.26.1.mjs
63bef319d33f6998c4c378f12710733d98f2007e8b0ff313cb80c978320800f4 update-manifest.json
@@ -1,14 +0,0 @@
@echo off
setlocal EnableExtensions
chcp 65001 >nul
title Vendoo GitHub Deploy Assistent
cd /d "%~dp0"
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -STA -File "%~dp0scripts\github-deploy.ps1"
set "EXITCODE=%ERRORLEVEL%"
if not "%EXITCODE%"=="0" (
echo.
echo [FEHLER] GitHub-Deployment wurde mit Exit-Code %EXITCODE% beendet.
echo.
pause
)
exit /b %EXITCODE%
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

@@ -1,323 +0,0 @@
# Vendoo 1.37.0
Vendoo 1.37.0 erweitert den modularen Plattformkern um einen nativen Sicherheitsbereich. Zugangsdaten werden verschlüsselt gespeichert, Inline-Skripte per CSP blockiert und Requests über eindeutige Request-/Correlation-IDs nachvollziehbar protokolliert.
## Security Foundation 1.37.0
- AES-256-GCM-Secret-Speicher mit separatem Master-Key
- automatische Migration bestehender Runtime-Secrets mit Sicherungskopie
- strikte Script-CSP ohne Inline-Skripte oder Inline-Eventhandler
- strukturierte JSON-Telemetrie und Request-/Correlation-IDs
- zentrale Input-Schema-Validierung für neue Kernel-Routen
- erweitertes Security-Dashboard ohne Klartext-Secrets
Vendoo 1.36.0 führt den ersten vollständig nativen Fachbereich auf dem Plattformkernel ein: den **Secure Theme Manager**. Benutzer können ihre persönliche Darstellung über geprüfte Eingabemasken wählen; Administratoren verwalten sichere Theme-Profile und den Systemstandard. Freies CSS, JavaScript, URLs oder Dateipfade werden nicht akzeptiert.
## Theme Manager 1.36.0
- Light, Dark, System und High Contrast
- persönliche Theme-Auswahl pro Benutzer
- UI-Dichte und reduzierte Bewegung
- eigene Theme-Profile auf Basis eines geprüften Basisthemes
- Live-Vorschau ohne sofortige Speicherung
- serverseitige Token- und Kontrastprüfung
- Import und Export validierter Theme-Profile
- administrativer Systemstandard
- Audit-Protokoll für Änderungen
- 42 Design Tokens einschließlich Komponenten-, Fokus- und Zielgrößen-Tokens
Die Theme-Verwaltung erfolgt vollständig über Vendoo. Es ist keine manuelle Bearbeitung von CSS-, JSON- oder Konfigurationsdateien erforderlich.
## Plattformarchitektur ab 1.35.0
- Kernel: `app/kernel/`
- Modulmanifeste: `app/modules/*/module.json`
- Architekturgrenzen: `app/architecture-boundaries.json`
- Design-Token-Quelle: `public/design-system/tokens/source.json`
- Theme-Vertrag: `public/design-system/theme-contract.json`
- Architektur-Gate: `npm run verify:architecture`
- vollständige technische Dokumentation: `docs/architecture/`
Die zwölf registrierten Bestandsmodule stehen bewusst auf `legacy-bridge`. Das zeigt transparent, welche Bereiche bereits einen Vertrag besitzen, aber noch schrittweise aus `server.mjs`, `public/app.js` und `public/style.css` herausgelöst werden müssen.
## Einfachster Start
- **Windows lokal oder Docker Desktop:** `setup.bat` doppelklicken, Ziel und Netzwerkzugriff auswählen, **Installieren** anklicken.
- **Linux/NAS/VPS:** `chmod +x setup.sh && ./setup.sh`, danach den geführten Assistenten verwenden.
- **VPS:** Domain eingeben; der integrierte Caddy-Stack übernimmt HTTPS automatisch, sobald DNS sowie Ports 80/443 korrekt auf den Server zeigen.
- **GitHub-Erstimport:** `GitHub-Deploy-Assistent.bat` starten. Der Assistent prüft Secrets/Laufzeitdaten, erstellt einen Release-Branch und öffnet die Browser-Anmeldung für Git.
## Sicherheit
- `.env`, Datenbanken, Uploads, Backups, Logs, Operations-Laufzeitdaten und FLUX-/ComfyUI-Modelle werden niemals committed.
- Der Erst-Admin-Code wird zufällig erzeugt und auf Windows in die Zwischenablage kopiert.
- Öffentliche VPS-Installationen verwenden ausschließlich HTTPS und veröffentlichen Vendoo nicht direkt auf Port 8124.
- Updates und Betriebsartwechsel löschen keine persistenten Daten.
---
## Vorheriger Stand 1.31.0
Vendoo 1.31.0 schafft die Grundlage für einen kontrollierten Mehrbenutzer- und Serverbetrieb. Rollen und Berechtigungen werden nicht nur in der Oberfläche, sondern an jeder geschützten API erzwungen. Artikelbearbeitung wird mit kurzlebigen Sperren koordiniert; Sitzungen, fehlgeschlagene Logins, Audit-Ereignisse und Rate Limits sind nachvollziehbar.
## Rollen
- **Administrator:** vollständiger Zugriff einschließlich Benutzer, Backups, Updates und Sicherheit.
- **Manager:** operative Verwaltung von Artikeln, Medien und Publishing, ohne Benutzer- oder Systemadministration.
- **Editor:** Artikel, Bilder, AI, FLUX, Bildproduktion und Qualitätsprüfung.
- **Publisher:** Artikel lesen, Qualität prüfen und Veröffentlichungen ausführen.
- **Leser:** reiner Lesezugriff.
## Sicherer Netzwerkbetrieb
Standardmäßig bindet Vendoo ausschließlich an `127.0.0.1`. Einen privaten LAN-Zugriff aktiviert der Installationsassistent nur nach bewusster Auswahl und setzt die erforderlichen Werte automatisch. Für öffentlichen Zugriff verwendet der VPS-Assistent den getrennten Caddy-Stack mit HTTPS; Port 8124 wird dabei nicht direkt veröffentlicht.
## Bestehende Funktionen
Alle Funktionen aus 1.30.0 bleiben enthalten: Operations Center, Publishing Hardening, Quality Center, Batch Image Factory, FLUX Studio Pro, Advanced Image Editor, Galerie und Browser-Extensions.
## Betriebszentrale (1.30.0)
Unter **Admin → System** stehen jetzt drei zusammenhängende Bereiche bereit:
- **Backup & Restore** mit SQLite-Snapshot, Datei-Prüfsummen, Integritätsprüfung, Download, Rotation und Wiederherstellungs-Staging
- **Update Center** mit Versionsprüfung, Paketvalidierung, Migrationsstatus, Sicherheitsbackup und bewusstem Offline-Anwenden über `setup.bat`
- **Extension-Diagnose** mit Paketversionen, Heartbeats, zuletzt verbundenen Browsern und Live-/Offline-Status
Update und Wiederherstellung ersetzen niemals während des laufenden Servers Dateien. Nach erfolgreicher Prüfung wird eine Operation vorbereitet und anschließend bei beendetem Vendoo über Setup-Menüpunkt 11 angewendet. Menüpunkt 12 stellt den zuvor gesicherten Programm- und Datenstand wieder her.
## Sicherheitsprinzipien
- Keine direkte Kopie einer geöffneten SQLite-Datei; Backups verwenden die SQLite-Backup-API.
- Jedes Backup enthält ein Manifest mit SHA-256-Prüfsummen und wird sofort geprüft.
- Eine Wiederherstellung erzeugt vorab automatisch ein vollständiges Sicherheitsbackup.
- Update-ZIPs mit `.env`, Datenbank, Uploads oder `node_modules` werden abgelehnt.
- Zugangsdaten aus `.env` werden nur nach ausdrücklicher Auswahl in manuelle Backups aufgenommen.
- Automatische Backups enthalten niemals `.env`.
- Update und Restore besitzen einen lokalen Rollback-Snapshot.
## Publishing Hardening (1.29.0)
- persistente Publishing-Queue für API- und Extension-Aufträge
- Schutz vor Doppelveröffentlichungen
- automatische Wiederholungen mit wachsendem Abstand
- Abbruch, manueller Retry und sichere Protokolllöschung
- Fehlerzentrale mit Audit-Ereignissen
- externe IDs, URLs und eBay Offer-IDs
- eBay Statusabgleich, Aktualisierung und Beenden über offizielle API
- Etsy Statusabgleich über offizielle API
- Vinted/Kleinanzeigen als bestätigungspflichtiger Extension-Workflow
- Wiederaufnahme laufender API-Aufträge nach Vendoo-Neustart
- geplante Veröffentlichungen werden an dieselbe gehärtete Queue übergeben
Vendoo 1.28.0 ergänzt die produktive **Batch Image Factory**. Mehrere Bilder aus der zentralen Galerie können in einem persistenten Auftrag über ein oder mehrere Produktionsprofile für Marktplätze, Webshops und Social Media verarbeitet werden. Ergebnisse bleiben nicht destruktiv, erscheinen wieder in der Galerie und lassen sich gesammelt als ZIP exportieren.
## Batch Image Factory (1.28.0)
- Hauptmenü **Bildproduktion** mit Quellenwahl aus der zentralen Bildergalerie
- Acht integrierte Ausgabeprofile sowie eigene speicherbare Profile
- Mehrfachprofile pro Auftrag und bis zu 200 Quellbilder
- Hintergrundentfernung, Sensitivität und Wasserzeichen als globale Auftragsoptionen
- persistente Job- und Positionshistorie mit Pause, Fortsetzen, Abbruch und Retry
- Wiederaufnahme nach Vendoo-Neustart
- nicht destruktive Ergebnisse unter `uploads/batch/`
- automatische Galerieintegration und ZIP-Export pro Auftrag
## Neu in 1.12.0
Der mobile QR-Upload bietet nun zwei eindeutige Wege: **Kamera öffnen** und **Mediathek auswählen**. Dadurch erzwingt das Smartphone nicht mehr ausschließlich die Kamera. Mehrere vorhandene Bilder können direkt gewählt werden; HEIC/HEIF werden nach Möglichkeit serverseitig zu JPG konvertiert.
OpenRouter wurde zusätzlich gehärtet: Vendoo erkennt Free-Bildmodelle präziser, prüft Bildinput-Fähigkeit, versucht mehrere kompatible Request-Formen und wechselt bei Fehlern automatisch zum nächsten Modell. Sind aktuell keine kostenlosen Bildmodelle vorhanden, zeigt die Diagnose das ausdrücklich an.
## Neu in 1.11.0
Der QR-Handy-Upload erzeugt jetzt automatisch Links mit der erkannten LAN-IP des Vendoo-PCs. Unter **Einstellungen → Vendoo LAN-Adresse für QR-Upload** kann die Adresse erkannt, geprüft und dauerhaft gespeichert werden. Die mobile Navigation wurde für Smartphone und Tablet komplett stabilisiert. Bei OpenRouter-Bildgenerierung versucht Vendoo automatisch mehrere passende Free-Modelle nacheinander und nutzt im Auto-Modus anschließend OpenAI als Fallback.
## Neu in 1.10.0
Vendoo unterstützt jetzt eine **AI-Job-Queue** für Bildgenerierung. Kleidung kann mit **1 bis 3** Varianten als **Model**, **Ghost Mannequin** oder **Flatlay** generiert werden. Im Listing-Editor gibt es zusätzlich eine **Historie früherer AI-Generierungen**, damit erzeugte Bilder schnell wiederverwendet werden können.
## Neu in 1.9.0
Die Einstellungen wurden um ein eigenes Steuerzentrum für **AI-Model-Fotos** erweitert. Dort lassen sich Provider, Free-Filter, Safety-Blocker, Standard-Preset, Variantenanzahl und das OpenAI-Fallback-Modell pflegen. Zusätzlich kann die UI die aktuell verfügbaren OpenRouter-Bildmodelle direkt laden und anzeigen.
## Neu in 1.8.0
Vendoo kann jetzt neben OpenAI auch OpenRouter für AI-Model-Fotos verwenden. Wenn `ai_model_photo_provider=auto` gesetzt ist und `OPENROUTER_API_KEY` vorhanden ist, fragt Vendoo automatisch aktuelle Bildmodelle von OpenRouter ab, filtert auf Bildausgabe und sofern aktiviert nur kostenlose Varianten. Gibt es kein passendes freies Modell mehr, fällt Vendoo sauber auf OpenAI zurück.
### Neue relevante Settings
- `ai_model_photo_provider`: `auto`, `openrouter`, `openai`
- `ai_model_photo_openrouter_free_only`: `1` oder `0`
- `ai_model_photo_openrouter_model`: optional feste OpenRouter-Model-ID
- `ai_model_photo_openai_model`: OpenAI-Fallback-Modell, Default `gpt-image-1`
### Neue ENV-Variablen
- `OPENROUTER_API_KEY`
- optional `OPENROUTER_SITE_URL`
- optional `OPENROUTER_APP_NAME`
## Neu in 1.7.0
Vendoo kann jetzt für geeignete Kleidungsstücke sichere AI-Model-Fotos erzeugen. Der Workflow prüft zuerst, ob ein Kleidungsartikel ohne Person vorliegt, blockiert sensible Kategorien und erstellt danach 13 zusätzliche Lifestyle-/Studio-Bilder mit fiktiven erwachsenen Personen oder alternative Ghost-Mannequin-/Flatlay-Varianten. Die Bilder lassen sich direkt in Generator und Listing-Editor übernehmen.
## Neu in 1.26.0
- Hauptnavigation mit **Neuer Artikel** direkt unter dem Dashboard und **Artikel** statt Listings
- repariertes Publish Center mit zuverlässigem Smart-Copy-Popup
- zoombare Medienvorschau mit Fit, 100 %, Mausrad und Verschieben
- kompakte lokale SVG-Iconbibliothek für Galerieaktionen
- aktualisierte Verkäufergebühren für eBay, Vinted, Kleinanzeigen und Etsy
- eigenes Extension Center für Chrome, Edge, Firefox und Safari
# Vendoo
Lokaler Multi-Plattform Listing-Generator mit AI, Lagerverwaltung und Publishing-System.
## Aktueller Entwicklungsstand
- Version: `1.37.0`
- UI-Slice: `UI 2026 / Slice 07 Cross-Browser Extensions, Responsive UI & Mobile Upload`
- Startseite: `Studio Flow`
- Tech Stack: Node.js, Express (ESM), Vanilla JS, SQLite (`better-sqlite3`)
Die vollständige Funktionsbeschreibung steht in [`FEATURES.md`](FEATURES.md). Die freigegebene Designrichtung liegt unter [`MockupDesign/`](MockupDesign/). Der vollständige Listing-Editor ist in [`docs/FULL_LISTING_EDITOR_2026.md`](docs/FULL_LISTING_EDITOR_2026.md) dokumentiert.
## Lokaler Start
```bash
npm install
npm start
```
Danach ist Vendoo standardmäßig unter `http://localhost:8124` erreichbar.
## Wichtige Sicherheitsregel
Nicht versionieren oder weitergeben:
- `.env`
- `db/vendoo.db*`
- `uploads/`
- Backups und Logs
- API-Schlüssel, OAuth-Tokens und SMTP-Passwörter
Die bereitgestellte Projektversion enthält ausschließlich `.env.example` und keine produktiven Laufzeitdaten.
## Browser-Erweiterungen
Die aktuellen Erweiterungen liegen getrennt unter `extensions/chrome`, `extensions/edge`, `extensions/firefox` und `extensions/safari`. Über den Vendoo-Menüpunkt **Extensions** wird der aktive Browser erkannt, der Installationsordner geöffnet und der Pfad kopiert. Safari benötigt auf macOS zusätzlich Xcode und die mitgelieferte WebExtension-Konvertierung.
## Mobiler Foto-Upload
Im Generator und im Listing-Editor kann ein zeitlich begrenzter QR-Code erzeugt werden. Nach dem Scan können Fotos direkt vom Smartphone aufgenommen und ohne Neuladen an Vendoo übertragen werden. Für andere Geräte muss Vendoo über eine erreichbare LAN-IP oder `PUBLIC_BASE_URL` geöffnet sein; `localhost` funktioniert nur auf demselben Gerät.
## Browser-Erweiterung 1.4.0
Die Erweiterungen für Chrome, Edge und Firefox verwenden jetzt eine kompakte, aktionsorientierte Oberfläche. Die primäre Aktion **Nur ausfüllen** trägt ein Listing in das geöffnete Vinted-Formular ein, ohne einen Entwurf zu speichern und ohne eine Veröffentlichung auszulösen. Abschlussaktionen sind davon deutlich getrennt.
## Aktueller UI-Stand
Slice 10 ergänzt das interaktive Dashboard, den aufgeräumten Studio Flow, robuste Publish-Initialisierung, ZIP-Fotodownloads und erweiterte Responsive-Gates.
## Branding
Logo, App-Icons, mobile Größen und Favicons liegen unter `public/brand/`. Die Browser-Erweiterungen für Chrome, Edge und Firefox verwenden dieselbe Icon-Familie.
## Local FLUX / ComfyUI
Vendoo can now prefer a local image backend for AI model photos. The intended order is: **Local FLUX / ComfyUI -> OpenRouter Free -> OpenAI**.
### What was added
- Settings for local URL, token, workflow path and install path
- Backend-only access to the local image server
- PowerShell bootstrap via `setup.ps1` or Settings UI
- Token regeneration for restricted local access
### Default assumptions
- ComfyUI is reachable at `http://127.0.0.1:8188`
- Workflow file: `local-ai/workflows/vendoo_flux_schnell_api.json`
- Vendoo talks to the local server from the backend, not directly from the browser
> Note: the included workflow template is a bootstrap starter and may need adjustment to the exact ComfyUI / FLUX node setup on the target machine.
## Vollautomatische lokale FLUX-Installation
Vendoo kann ComfyUI Portable und optional FLUX.1-schnell FP8 direkt aus der Einstellungsseite oder über `setup.bat` installieren.
### Über die Benutzeroberfläche
1. **Einstellungen → AI-Model-Fotos** öffnen.
2. Als Provider `Auto` oder `Nur lokales FLUX / ComfyUI` auswählen.
3. Installationsoptionen wählen.
4. **Lokales FLUX installieren** anklicken.
5. Den Fortschritt direkt in Vendoo verfolgen.
### Über setup.bat
- `7` lokales FLUX / ComfyUI installieren oder aktualisieren
- `8` Status anzeigen
- `9` lokalen Server starten
- `10` lokalen Server stoppen
### Sicherheitsmodell
ComfyUI wird ausschließlich an `127.0.0.1:8188` gebunden. Der Browser greift nicht direkt auf ComfyUI zu; nur das Vendoo-Backend sendet Bildjobs. Standardmäßig werden Remote-URLs abgelehnt. Ein zufälliger lokaler Token wird zusätzlich in der `.env` gespeichert. Das schützt den Dienst vor Zugriff aus dem LAN, ersetzt aber keine vollständige Prozessisolation gegenüber anderer Software auf demselben Windows-PC.
### Große Downloads
Der Modell-Download ist optional und wird vor dem Start ausdrücklich bestätigt. Bereits vorhandene ComfyUI- oder Modelldateien werden nicht ohne `Force` überschrieben. Downloads und Installationsfortschritt werden protokolliert.
## FLUX installer status and recovery
The local FLUX installer now records a detailed, resumable state in `local-ai/install-state.json`. The settings page displays individual checks for 7-Zip, the ComfyUI archive, embedded Python, ComfyUI, the FLUX model, workflow and runtime scripts. Failed installations can be started again without blindly discarding complete downloads.
The PowerShell 5.1 path bug that could turn `C:\Program Files\7-Zip\7z.exe` into the command `C` has been fixed.
## FLUX installer status hotfix (1.14.2)
The local FLUX installer now supervises 7-Zip instead of waiting without feedback. During extraction Vendoo shows files, extracted MB, elapsed time, heartbeat and the current 7-Zip log. A stale installer is marked as **stalled** and can be resumed without downloading the complete ComfyUI archive again.
## FLUX Studio ab 1.21.0
Vendoo enthält einen eigenen Hauptmenüpunkt **FLUX Studio**. Dort werden Bilder ausschließlich aus freien Prompts über das lokale ComfyUI/FLUX erzeugt. Einstellbar sind Stil, Ausgabeformat, Seed und Inferenzschritte. Ergebnisse werden in einer lokalen Bibliothek gespeichert, können heruntergeladen, in den Listing-Generator übernommen oder mit dem integrierten Editor nachbearbeitet werden.
Der frühere FASHN-/Virtual-Try-on-Stack wurde vollständig aufgegeben. Es werden kein Python-, Torch-, ONNX- oder separater VTO-Dienst mehr installiert. Beim ersten Start des aktualisierten Setups werden alte VTO-Runtime, Autostarts und Einstellungen entfernt; eigene frühere Modelbilder werden zur Sicherheit nach `uploads/ai-generated/legacy-models` verschoben.
### Update
1. Vendoo schließen.
2. Paketinhalt über die bestehende Installation kopieren und Dateien ersetzen.
3. `setup.bat` starten und **Reparieren** ausführen.
4. Vendoo starten und den Menüpunkt **FLUX Studio** öffnen.
## FLUX Studio Pro ab 1.22.0
Slice 30 erweitert das reine Prompt-Studio zu einem persistenten Job-Center. Aufträge können 1, 2 oder 4 Varianten mit eigenen Seeds erzeugen. Seed Lock, Wiederholen, „Ähnlich erneut erzeugen“, Favoriten, Queue-/History-Anbindung, System-/GPU-Daten und Wiederaufnahme nach Vendoo-Neustart sind integriert.
Die Fortschrittsanzeige verwendet im FLUX-Studio-Pro-Pfad ausschließlich reale Phasen und verstrichene Laufzeit. Es werden keine Prozentwerte aus einer angenommenen Renderdauer errechnet.
### Update auf 1.22.0
1. Vendoo und ComfyUI-Fenster schließen.
2. Den Inhalt des Paket-Unterordners `vendoo` über die bestehende Installation kopieren und Dateien ersetzen.
3. Den bestehenden Zielordner und Laufzeitdaten nicht löschen.
4. `setup.bat` starten und **3 Update** ausführen.
5. Bei Bedarf **9 Lokales FLUX / ComfyUI starten**, danach **8 Status** prüfen.
6. Vendoo starten und FLUX Studio öffnen.
## Artikel Quality Center
Vendoo 1.28.0 prüft Artikel vor dem Publishing auf Blocker, Vollständigkeit, Bildqualität, mögliche Duplikate und Plattformtauglichkeit. AI-Verbesserungen werden nur als Vorschlag angezeigt und erst nach ausdrücklicher Bestätigung gespeichert.
## Installationsziel wählen (1.36.0)
`setup.bat` führt auf Windows durch lokale Node-Installation oder Docker Desktop. Für Linux, NAS, Portainer und VPS steht `setup.sh` bereit. Beide Wege verwenden dieselbe `.env`, dieselben Compose-Dateien und dieselben persistenten Datenbereiche.
@@ -1,88 +0,0 @@
# Sicherheit
## Vertrauliche Dateien
Folgende Dateien dürfen niemals in Git oder öffentliche Pakete gelangen:
- `.env`
- `db/*.db`, `db/*.db-wal`, `db/*.db-shm`
- `uploads/`
- Backups, Logs und Session-Daten
- private Schlüssel und Zertifikate
## Online-Betrieb
Vendoo darf nicht durch eine direkte Portfreigabe von Port 8124 veröffentlicht werden. Für öffentliche Nutzer ist eine getrennte Server-/VPS-Instanz hinter HTTPS und Reverse Proxy vorgesehen.
## Meldung von Sicherheitsproblemen
Sicherheitsprobleme nicht mit Zugangsdaten oder personenbezogenen Daten in öffentliche Issues schreiben.
## Lokaler FLUX / ComfyUI
- ComfyUI wird standardmäßig nur an `127.0.0.1` gebunden.
- Vendoo blockiert Remote-ComfyUI-URLs, solange `LOCAL_IMAGE_ALLOW_REMOTE` nicht ausdrücklich aktiviert wird.
- Die ComfyUI-Oberfläche wird nicht über das LAN veröffentlicht.
- API-Aufrufe erfolgen serverseitig durch Vendoo.
- Ein zufälliger Token wird für die lokale Integrationskonfiguration erzeugt.
- Andere Prozesse auf demselben Windows-Rechner können theoretisch ebenfalls auf einen localhost-Dienst zugreifen; für echte Prozessisolation wäre ein separates Windows-Konto oder eine VM erforderlich.
## FLUX Studio
- ComfyUI bleibt standardmäßig ausschließlich an `127.0.0.1` gebunden.
- Das FLUX Studio akzeptiert nur Textprompts und erzeugt Dateien unter `uploads/ai-generated`.
- API-Pfade für Bibliothek und Bearbeitungen werden serverseitig auf dieses Verzeichnis begrenzt.
- Start und Stopp der lokalen Engine erfordern eine Admin-Rolle.
- Bearbeitungen erzeugen neue Dateien; Originalausgaben werden nicht still überschrieben.
## Operations Center, Backups und Updates
- Backups werden mit einem Manifest und SHA-256-Prüfsummen erzeugt und vor der Freigabe verifiziert.
- Sicherungen, die `.env` enthalten, enthalten möglicherweise API-Schlüssel, Tokens und Zugangsdaten. Sie sind wie Passwörter zu behandeln und dürfen nicht unverschlüsselt weitergegeben werden.
- Restore- und Update-Archive werden vor der Anwendung in einem lokalen Staging-Bereich geprüft.
- Archive mit Pfad-Traversal, absoluten Pfaden oder unzulässigen Laufzeitdaten werden abgewiesen.
- Updates dürfen keine `.env`, produktive Datenbank, Uploads, Backups, Logs, Modelle oder `node_modules` mitbringen.
- Das eigentliche Anwenden erfolgt nur bei gestopptem Vendoo über `setup.bat` und erzeugt vorher einen Rollback-Snapshot.
- Eine optionale Update-Manifest-URL sollte ausschließlich über HTTPS und aus einer kontrollierten Quelle verwendet werden.
- Extension-Heartbeats enthalten nur Diagnosemetadaten wie Browser, Version, Plattform und Zeitpunkt; keine Formularinhalte oder Zugangsdaten.
## Mehrbenutzer- und Server-Sicherheit ab 1.31.0
- Vendoo bindet standardmäßig an `127.0.0.1`. LAN-Zugriff muss ausdrücklich über `VENDOO_BIND_HOST=0.0.0.0` aktiviert werden.
- Öffentlicher Betrieb ausschließlich über HTTPS und einen korrekt konfigurierten Reverse Proxy. `VENDOO_TRUST_PROXY=true` nur setzen, wenn der Proxy vertrauenswürdig ist und Client-IP-Header kontrolliert.
- `VENDOO_ALLOWED_HOSTS` und `VENDOO_ALLOWED_ORIGINS` eng begrenzen.
- Rollen ersetzen keine Betriebssystemrechte: Datenbank, `.env`, Backups und Uploads müssen auf Dateisystemebene geschützt bleiben.
- Bearbeitungssperren verhindern parallele Änderungen, ersetzen aber keine Backups.
- Audit-Logs können personenbezogene Betriebsdaten wie Benutzer, IP und Aktionen enthalten; Aufbewahrung und Zugriff müssen organisatorisch geregelt werden.
## Architektur-Sicherheitsregeln ab 1.35.0
- Neue Kernel-Routen sind Deny-by-default und benötigen eine registrierte Policy.
- Modulmanifeste, Abhängigkeiten, Capabilities und Ownership werden vor dem Start validiert.
- Zyklische Abhängigkeiten, fehlende Capabilities und doppelte Ressourcen-Ownership blockieren den Kernelstart.
- Drittanbieter-Erweiterungen dürfen nicht im Vendoo-Hauptprozess ausgeführt werden.
- Themes dürfen nur freigegebene, typisierte Design Tokens verändern; freies CSS, JavaScript und externe URLs sind verboten.
- Der Event Bus ordnet Listener einem Owner zu, damit Module beim Stoppen ihre Listener vollständig entfernen können.
- Das Architektur-Gate `npm run verify:architecture` ist verpflichtender Bestandteil von CI und Releases.
## Theme-Sicherheit ab 1.36.0
- Theme-Profile akzeptieren ausschließlich bekannte, typisierte Design Tokens.
- Freies CSS, JavaScript, HTML, URLs und Dateipfade sind nicht zulässig.
- Alle Werte werden im Browser zur Benutzerführung und erneut auf dem Server validiert.
- Normale Benutzer können nur die eigene Theme-Präferenz verändern.
- Theme-Profile und Systemstandard erfordern `settings.manage`.
- Theme-Änderungen werden auditiert.
- Importierte Profile durchlaufen dieselbe Validierung wie manuell erstellte Profile.
- Kontrastprüfungen verhindern nicht automatisch jede bewusste administrative Gestaltung, zeigen problematische Paare aber vor dem Speichern deutlich an.
## Security Foundation ab 1.37.0
Zugangsdaten werden bevorzugt im verschlüsselten Secret-Speicher unter dem persistenten Konfigurationsbereich abgelegt. Die Verschlüsselung verwendet AES-256-GCM; der Master-Key liegt getrennt und wird nicht in Git oder Release-Pakete aufgenommen. Bestehende Secrets aus der Runtime-Konfiguration werden beim ersten Start gesichert, verschlüsselt migriert und aus der Klartextdatei entfernt.
Die Weboberfläche verwendet eine erzwungene Content Security Policy ohne Inline-Skripte und Inline-Eventhandler. Request- und Correlation-IDs werden in Antworten ausgegeben und in der strukturierten Telemetrie geführt.
@@ -1,13 +0,0 @@
# Drittanbieter-Hinweise für lokale AI-Engines
## FLUX / ComfyUI
Vendoo kann eine lokale ComfyUI-Installation mit einem FLUX-kompatiblen Modell ansteuern. ComfyUI, Modelle, Custom Nodes und deren Gewichte werden nicht als Vendoo-eigene Software ausgegeben. Für jede installierte Komponente gelten die jeweiligen Lizenz- und Nutzungsbedingungen der Herausgeber.
Vendoo liefert keine FASHN-VTON-, Python-, Torch-, ONNX- oder Human-Parser-Komponenten mehr aus und installiert diese auch nicht mehr.
## Lucide Icons
Die lokale Vendoo-Iconbibliothek verwendet eine kompakte Auswahl von Lucide-Icon-Geometrien.
Lucide steht unter der ISC-Lizenz. Projekt: https://lucide.dev/
@@ -1,19 +0,0 @@
{
"schemaVersion": 1,
"architecture": "modular-monolith",
"rules": {
"modulePrefix": "vendoo.",
"denyImplicitRoutes": true,
"denyCrossModuleDatabaseAccess": true,
"denyCrossModuleInternalImports": true,
"thirdPartyExtensionsInMainProcess": false,
"themeCustomCss": false,
"themeTokensOnly": true
},
"migration": {
"mode": "strangler",
"legacyBridgeStatus": "legacy-bridge",
"frameworkMigration": false,
"databaseReplacement": false
}
}
@@ -1,34 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://vendoo.local/contracts/module.schema.json",
"title": "Vendoo Module Manifest",
"type": "object",
"additionalProperties": false,
"required": ["schemaVersion", "id", "name", "version", "type", "status", "requires", "permissions", "provides", "consumes", "owns"],
"properties": {
"schemaVersion": { "const": 1 },
"id": { "type": "string", "pattern": "^vendoo\\.[a-z][a-z0-9-]*$" },
"name": { "type": "string", "minLength": 1, "maxLength": 80 },
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$" },
"type": { "enum": ["core", "feature", "adapter", "extension-host"] },
"status": { "enum": ["native", "legacy-bridge", "disabled"] },
"description": { "type": "string", "maxLength": 500 },
"requires": { "$ref": "#/$defs/moduleIds" },
"permissions": { "$ref": "#/$defs/capabilities" },
"provides": { "$ref": "#/$defs/capabilities" },
"consumes": { "$ref": "#/$defs/capabilities" },
"owns": { "$ref": "#/$defs/capabilities" }
},
"$defs": {
"moduleIds": {
"type": "array",
"uniqueItems": true,
"items": { "type": "string", "pattern": "^vendoo\\.[a-z][a-z0-9-]*$" }
},
"capabilities": {
"type": "array",
"uniqueItems": true,
"items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*(?:\\.[a-z][a-z0-9-]*)+$" }
}
}
}
@@ -1,49 +0,0 @@
export const SECRET_DEFINITIONS = Object.freeze({
ANTHROPIC_API_KEY: { label: 'Anthropic API-Key', category: 'AI', editable: true },
OPENAI_API_KEY: { label: 'OpenAI API-Key', category: 'AI', editable: true },
OPENROUTER_API_KEY: { label: 'OpenRouter API-Key', category: 'AI', editable: true },
ETSY_API_KEY: { label: 'Etsy API-Key', category: 'Marktplatz', editable: true },
ETSY_ACCESS_TOKEN: { label: 'Etsy Access Token', category: 'Marktplatz', editable: false },
ETSY_REFRESH_TOKEN: { label: 'Etsy Refresh Token', category: 'Marktplatz', editable: false },
EBAY_CLIENT_SECRET: { label: 'eBay Client Secret', category: 'Marktplatz', editable: true },
EBAY_ACCESS_TOKEN: { label: 'eBay Access Token', category: 'Marktplatz', editable: false },
EBAY_REFRESH_TOKEN: { label: 'eBay Refresh Token', category: 'Marktplatz', editable: false },
LOCAL_IMAGE_TOKEN: { label: 'FLUX Dienst-Token', category: 'FLUX', editable: true },
SMTP_PASS: { label: 'SMTP-Passwort', category: 'E-Mail', editable: true },
VENDOO_SETUP_TOKEN: { label: 'Ersteinrichtungs-Token', category: 'System', editable: false },
});
export const SECRET_NAMES = Object.freeze(Object.keys(SECRET_DEFINITIONS));
const SECRET_NAME = /^[A-Z][A-Z0-9_]{2,80}$/;
export function validateSecretName(name) {
const normalized = String(name || '').trim();
if (!SECRET_NAME.test(normalized) || !SECRET_DEFINITIONS[normalized]) {
const error = new Error(`Unbekanntes Secret: ${normalized || '(leer)'}`);
error.code = 'SECRET_NAME_INVALID';
throw error;
}
return normalized;
}
export function validateSecretValue(value) {
const normalized = String(value ?? '');
if (/\r|\n|\0/.test(normalized)) {
const error = new Error('Secrets dürfen keine Zeilenumbrüche oder Nullbytes enthalten.');
error.code = 'SECRET_VALUE_INVALID';
throw error;
}
if (Buffer.byteLength(normalized, 'utf8') > 16_384) {
const error = new Error('Secret ist zu groß.');
error.code = 'SECRET_VALUE_TOO_LARGE';
throw error;
}
return normalized;
}
export function maskSecret(value) {
const text = String(value || '');
if (!text) return '';
if (text.length <= 4) return '••••';
return `••••••••${text.slice(-4)}`;
}
@@ -1,169 +0,0 @@
import { readFileSync } from 'fs';
import { join } from 'path';
import { APP_ROOT } from '../../../lib/runtime-paths.mjs';
import { PlatformError } from '../../kernel/errors.mjs';
const source = JSON.parse(readFileSync(join(APP_ROOT, 'public', 'design-system', 'tokens', 'source.json'), 'utf8'));
const BUILTIN_THEME_IDS = new Set([...source.themes, 'system', 'inherit']);
const HEX_COLOR = /^#(?:[0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
const RGB_COLOR = /^rgba?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)(?:\s*,\s*(0|1|0?\.\d+))?\s*\)$/i;
const DIMENSION = /^-?\d+(?:\.\d+)?px$/i;
const THEME_ID = /^[a-z][a-z0-9-]{2,39}$/;
function expandHex(value) {
const hex = value.replace('#', '');
if (hex.length === 3 || hex.length === 4) return hex.split('').map(char => char + char).join('');
return hex;
}
function parseColor(value) {
const raw = String(value || '').trim();
if (HEX_COLOR.test(raw)) {
const hex = expandHex(raw);
return [0, 2, 4].map(index => Number.parseInt(hex.slice(index, index + 2), 16));
}
const match = raw.match(RGB_COLOR);
if (!match) return null;
const channels = match.slice(1, 4).map(Number);
return channels.every(channel => Number.isFinite(channel) && channel >= 0 && channel <= 255) ? channels : null;
}
function validColor(value) {
if (!parseColor(value)) return false;
const match = String(value).trim().match(RGB_COLOR);
if (!match) return true;
const alpha = match[4] === undefined ? 1 : Number(match[4]);
return Number.isFinite(alpha) && alpha >= 0 && alpha <= 1;
}
function validateValue(token, value) {
const raw = String(value ?? '').trim();
if (token.type === 'color') return validColor(raw);
if (token.type === 'dimension') {
if (!DIMENSION.test(raw)) return false;
const numeric = Number.parseFloat(raw);
if (token.min !== undefined && numeric < Number(token.min)) return false;
if (token.max !== undefined && numeric > Number(token.max)) return false;
return true;
}
return false;
}
function relativeLuminance(value) {
const rgb = parseColor(value);
if (!rgb) return null;
const linear = rgb.map(channel => {
const normalized = channel / 255;
return normalized <= 0.03928 ? normalized / 12.92 : ((normalized + 0.055) / 1.055) ** 2.4;
});
return 0.2126 * linear[0] + 0.7152 * linear[1] + 0.0722 * linear[2];
}
export function contrastRatio(foreground, background) {
const first = relativeLuminance(foreground);
const second = relativeLuminance(background);
if (first === null || second === null) return null;
const lighter = Math.max(first, second);
const darker = Math.min(first, second);
return (lighter + 0.05) / (darker + 0.05);
}
export function getBaseThemeValues(themeId = 'light') {
const base = source.themes.includes(themeId) ? themeId : 'light';
return Object.fromEntries(Object.entries(source.tokens).map(([name, token]) => [name, token[base]]));
}
export function resolveThemeValues({ baseTheme = 'light', values = {} } = {}) {
return Object.freeze({ ...getBaseThemeValues(baseTheme), ...values });
}
export function evaluateThemeAccessibility({ baseTheme = 'light', values = {} } = {}) {
const resolved = resolveThemeValues({ baseTheme, values });
const checks = [
['primary-on-canvas', 'color.ink', 'color.canvas', 4.5],
['primary-on-surface', 'color.ink', 'color.surface', 4.5],
['secondary-on-surface', 'color.inkSecondary', 'color.surface', 4.5],
['muted-on-surface', 'color.inkMuted', 'color.surface', 3],
['brand-on-surface', 'color.brand', 'color.surface', 3],
['danger-on-surface', 'color.danger', 'color.surface', 3],
['line-on-surface', 'color.lineStrong', 'color.surface', 3],
].map(([id, foregroundToken, backgroundToken, minimum]) => {
const ratio = contrastRatio(resolved[foregroundToken], resolved[backgroundToken]);
return {
id,
foregroundToken,
backgroundToken,
ratio: ratio === null ? null : Number(ratio.toFixed(2)),
minimum,
ok: ratio !== null && ratio >= minimum,
};
});
return Object.freeze({
ok: checks.every(check => check.ok),
checks: Object.freeze(checks),
failures: Object.freeze(checks.filter(check => !check.ok)),
});
}
export function getThemeContract() {
return {
schemaVersion: source.schemaVersion,
contractVersion: source.contractVersion,
themes: [...source.themes],
tokens: Object.fromEntries(Object.entries(source.tokens).map(([name, token]) => [name, {
css: token.css,
type: token.type,
customizable: Boolean(token.customizable),
label: token.label || name,
group: token.group || name.split('.')[0],
...(token.min !== undefined ? { min: token.min } : {}),
...(token.max !== undefined ? { max: token.max } : {}),
}])),
};
}
export function getBuiltinThemes() {
return source.themes.map(id => ({
id,
name: ({ light: 'Hell', dark: 'Dunkel', contrast: 'Hoher Kontrast' })[id] || id,
base_theme: id,
builtin: true,
values: {},
resolved_values: getBaseThemeValues(id),
accessibility: evaluateThemeAccessibility({ baseTheme: id }),
}));
}
export function validateThemeDefinition(theme, { allowExistingId = false } = {}) {
if (!theme || typeof theme !== 'object' || Array.isArray(theme)) {
throw new PlatformError('Theme-Definition ist ungültig.', { code: 'THEME_INVALID', status: 400, expose: true });
}
const id = String(theme.id || '').trim().toLowerCase();
const name = String(theme.name || '').trim();
const baseTheme = String(theme.base_theme || theme.baseTheme || 'light').trim().toLowerCase();
if (!THEME_ID.test(id) || BUILTIN_THEME_IDS.has(id)) throw new PlatformError('Theme-ID ist ungültig oder reserviert.', { code: 'THEME_ID_INVALID', status: 400, expose: true });
if (!allowExistingId && !id.startsWith('custom-')) throw new PlatformError('Eigene Theme-IDs müssen mit custom- beginnen.', { code: 'THEME_ID_PREFIX', status: 400, expose: true });
if (!name || name.length > 80) throw new PlatformError('Theme-Name ist ungültig.', { code: 'THEME_NAME_INVALID', status: 400, expose: true });
if (!source.themes.includes(baseTheme)) throw new PlatformError('Basis-Theme ist ungültig.', { code: 'THEME_BASE_INVALID', status: 400, expose: true });
const values = {};
for (const [tokenName, value] of Object.entries(theme.values || {})) {
const token = source.tokens[tokenName];
if (!token || !token.customizable) throw new PlatformError(`Token ist nicht anpassbar: ${tokenName}`, { code: 'THEME_TOKEN_FORBIDDEN', status: 400, expose: true });
if (!validateValue(token, value)) throw new PlatformError(`Ungültiger Wert für ${tokenName}.`, { code: 'THEME_VALUE_INVALID', status: 400, expose: true });
values[tokenName] = String(value).trim();
}
const accessibility = evaluateThemeAccessibility({ baseTheme, values });
return Object.freeze({ schemaVersion: 1, id, name, base_theme: baseTheme, values: Object.freeze(values), accessibility });
}
export function validateThemePreference(input, { customThemeExists = () => false } = {}) {
const themeId = String(input?.theme_id || input?.themeId || 'inherit').trim().toLowerCase();
const density = String(input?.density || 'comfortable').trim().toLowerCase();
const reducedMotion = String(input?.reduced_motion || input?.reducedMotion || 'system').trim().toLowerCase();
if (![...BUILTIN_THEME_IDS].includes(themeId) && !customThemeExists(themeId)) {
throw new PlatformError('Gewähltes Theme existiert nicht.', { code: 'THEME_NOT_FOUND', status: 404, expose: true });
}
if (!['compact', 'comfortable', 'spacious'].includes(density)) throw new PlatformError('UI-Dichte ist ungültig.', { code: 'THEME_DENSITY_INVALID', status: 400, expose: true });
if (!['system', 'reduce', 'allow'].includes(reducedMotion)) throw new PlatformError('Bewegungseinstellung ist ungültig.', { code: 'THEME_MOTION_INVALID', status: 400, expose: true });
return Object.freeze({ theme_id: themeId, density, reduced_motion: reducedMotion });
}
@@ -1,31 +0,0 @@
export class PlatformError extends Error {
constructor(message, { code = 'PLATFORM_ERROR', status = 500, details = null, expose = false, cause = undefined } = {}) {
super(String(message || 'Unbekannter Plattformfehler'), { cause });
this.name = 'PlatformError';
this.code = String(code || 'PLATFORM_ERROR');
this.status = Number.isInteger(status) ? status : 500;
this.details = details;
this.expose = Boolean(expose || this.status < 500);
}
}
export function normalizePlatformError(error) {
if (error instanceof PlatformError) return error;
return new PlatformError(error?.message || 'Interner Serverfehler', {
code: error?.code || 'INTERNAL_ERROR',
status: Number.isInteger(error?.status) ? error.status : 500,
details: error?.details || null,
expose: Boolean(error?.expose),
cause: error,
});
}
export function platformErrorPayload(error, requestId = null) {
const normalized = normalizePlatformError(error);
return {
error: normalized.expose ? normalized.message : 'Interner Serverfehler',
code: normalized.code,
request_id: requestId || null,
...(normalized.expose && normalized.details ? { details: normalized.details } : {}),
};
}
@@ -1,77 +0,0 @@
import { PlatformError } from './errors.mjs';
const EVENT_PATTERN = /^[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+$/;
export class EventBus {
#listeners = new Map();
#maxListeners;
constructor({ maxListenersPerEvent = 50 } = {}) {
this.#maxListeners = Math.max(1, Number(maxListenersPerEvent) || 50);
}
on(eventName, handler, { owner = 'core', once = false } = {}) {
if (!EVENT_PATTERN.test(String(eventName))) {
throw new PlatformError(`Ungültiger Eventname: ${eventName}`, { code: 'EVENT_NAME_INVALID', status: 500 });
}
if (typeof handler !== 'function') {
throw new PlatformError('Event-Handler muss eine Funktion sein.', { code: 'EVENT_HANDLER_INVALID', status: 500 });
}
const listeners = this.#listeners.get(eventName) || [];
if (listeners.length >= this.#maxListeners) {
throw new PlatformError(`Zu viele Listener für ${eventName}.`, { code: 'EVENT_LISTENER_LIMIT', status: 500 });
}
const entry = Object.freeze({ handler, owner: String(owner || 'core'), once: Boolean(once) });
listeners.push(entry);
this.#listeners.set(eventName, listeners);
return () => this.off(eventName, handler);
}
once(eventName, handler, options = {}) {
return this.on(eventName, handler, { ...options, once: true });
}
off(eventName, handler) {
const listeners = this.#listeners.get(eventName) || [];
const remaining = listeners.filter(entry => entry.handler !== handler);
if (remaining.length) this.#listeners.set(eventName, remaining);
else this.#listeners.delete(eventName);
return remaining.length !== listeners.length;
}
removeOwner(owner) {
let removed = 0;
for (const [eventName, listeners] of this.#listeners) {
const remaining = listeners.filter(entry => {
const match = entry.owner === owner;
if (match) removed += 1;
return !match;
});
if (remaining.length) this.#listeners.set(eventName, remaining);
else this.#listeners.delete(eventName);
}
return removed;
}
async emit(eventName, payload = null, context = {}) {
const listeners = [...(this.#listeners.get(eventName) || [])];
const results = [];
for (const entry of listeners) {
try {
results.push({ owner: entry.owner, ok: true, value: await entry.handler(payload, Object.freeze({ ...context, eventName })) });
} catch (error) {
results.push({ owner: entry.owner, ok: false, error });
} finally {
if (entry.once) this.off(eventName, entry.handler);
}
}
return results;
}
snapshot() {
return [...this.#listeners.entries()].map(([event, listeners]) => ({
event,
listeners: listeners.map(entry => ({ owner: entry.owner, once: entry.once })),
}));
}
}
@@ -1,59 +0,0 @@
import { PlatformError } from './errors.mjs';
const FLAG_PATTERN = /^[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+$/;
function envKey(flag) {
return `VENDOO_FEATURE_${flag.replace(/[^a-z0-9]/gi, '_').toUpperCase()}`;
}
function parseBoolean(value, fallback) {
if (value === undefined || value === null || value === '') return fallback;
if (/^(1|true|yes|on)$/i.test(String(value))) return true;
if (/^(0|false|no|off)$/i.test(String(value))) return false;
throw new PlatformError(`Ungültiger Feature-Flag-Wert: ${value}`, { code: 'FEATURE_FLAG_VALUE_INVALID', status: 500 });
}
export class FeatureFlagRegistry {
#flags = new Map();
define(name, { defaultValue = false, owner = 'vendoo.system', description = '', mutable = false } = {}) {
const normalized = String(name || '');
if (!FLAG_PATTERN.test(normalized)) {
throw new PlatformError(`Ungültiger Feature-Flag: ${normalized}`, { code: 'FEATURE_FLAG_NAME_INVALID', status: 500 });
}
if (this.#flags.has(normalized)) {
throw new PlatformError(`Feature-Flag bereits definiert: ${normalized}`, { code: 'FEATURE_FLAG_DUPLICATE', status: 500 });
}
const configured = parseBoolean(process.env[envKey(normalized)], Boolean(defaultValue));
this.#flags.set(normalized, {
name: normalized,
value: configured,
defaultValue: Boolean(defaultValue),
owner: String(owner),
description: String(description),
mutable: Boolean(mutable),
source: process.env[envKey(normalized)] === undefined ? 'default' : 'environment',
});
return configured;
}
isEnabled(name) {
if (!this.#flags.has(name)) {
throw new PlatformError(`Unbekannter Feature-Flag: ${name}`, { code: 'FEATURE_FLAG_UNKNOWN', status: 500 });
}
return this.#flags.get(name).value;
}
set(name, value) {
const flag = this.#flags.get(name);
if (!flag) throw new PlatformError(`Unbekannter Feature-Flag: ${name}`, { code: 'FEATURE_FLAG_UNKNOWN', status: 404, expose: true });
if (!flag.mutable) throw new PlatformError(`Feature-Flag ist nicht zur Laufzeit änderbar: ${name}`, { code: 'FEATURE_FLAG_IMMUTABLE', status: 409, expose: true });
flag.value = Boolean(value);
flag.source = 'runtime';
return flag.value;
}
list() {
return [...this.#flags.values()].map(flag => ({ ...flag }));
}
}
@@ -1,37 +0,0 @@
import { PlatformError } from './errors.mjs';
function fail(message, field) {
throw new PlatformError(message, { code: 'INPUT_VALIDATION_FAILED', status: 400, expose: true, details: { field } });
}
export function objectSchema(fields, { allowUnknown = false } = {}) {
const contract = Object.freeze({ ...fields });
return input => {
const source = input && typeof input === 'object' && !Array.isArray(input) ? input : {};
const output = {};
if (!allowUnknown) for (const key of Object.keys(source)) if (!contract[key]) fail(`Unbekanntes Eingabefeld: ${key}`, key);
for (const [name, rule] of Object.entries(contract)) {
let value = source[name];
if (value === undefined || value === null) {
if (rule.required) fail(`${name} ist erforderlich.`, name);
continue;
}
if (rule.type === 'string') {
value = String(value);
if (rule.trim !== false) value = value.trim();
if (rule.minLength && value.length < rule.minLength) fail(`${name} ist zu kurz.`, name);
if (rule.maxLength && value.length > rule.maxLength) fail(`${name} ist zu lang.`, name);
if (rule.pattern && !rule.pattern.test(value)) fail(`${name} besitzt ein ungültiges Format.`, name);
} else if (rule.type === 'boolean') {
if (typeof value !== 'boolean') fail(`${name} muss true oder false sein.`, name);
} else if (rule.type === 'number') {
value = Number(value);
if (!Number.isFinite(value)) fail(`${name} muss eine Zahl sein.`, name);
if (rule.min !== undefined && value < rule.min) fail(`${name} ist zu klein.`, name);
if (rule.max !== undefined && value > rule.max) fail(`${name} ist zu groß.`, name);
}
output[name] = value;
}
return Object.freeze(output);
};
}
@@ -1,49 +0,0 @@
import { PlatformError } from './errors.mjs';
export class LifecycleManager {
#state = 'created';
#hooks = [];
register({ id, order = 100, start = async () => {}, stop = async () => {} }) {
if (!id || this.#hooks.some(hook => hook.id === id)) {
throw new PlatformError(`Ungültiger oder doppelter Lifecycle-Hook: ${id}`, { code: 'LIFECYCLE_HOOK_INVALID' });
}
this.#hooks.push({ id: String(id), order: Number(order) || 100, start, stop, state: 'registered' });
}
async start(context) {
if (!['created', 'stopped'].includes(this.#state)) throw new PlatformError(`Kernel kann aus Zustand ${this.#state} nicht starten.`, { code: 'LIFECYCLE_STATE_INVALID' });
this.#state = 'starting';
const started = [];
try {
for (const hook of [...this.#hooks].sort((a, b) => a.order - b.order)) {
hook.state = 'starting';
await hook.start(context);
hook.state = 'running';
started.push(hook);
}
this.#state = 'running';
} catch (error) {
for (const hook of started.reverse()) {
try { await hook.stop({ ...context, rollback: true }); } catch {}
hook.state = 'stopped';
}
this.#state = 'failed';
throw error;
}
}
async stop(context) {
if (!['running', 'starting'].includes(this.#state)) return;
this.#state = 'stopping';
for (const hook of [...this.#hooks].sort((a, b) => b.order - a.order)) {
if (hook.state !== 'running') continue;
try { await hook.stop(context); } finally { hook.state = 'stopped'; }
}
this.#state = 'stopped';
}
snapshot() {
return { state: this.#state, hooks: this.#hooks.map(({ start: _s, stop: _t, ...hook }) => ({ ...hook })) };
}
}
@@ -1,47 +0,0 @@
import { PlatformError } from './errors.mjs';
const MODULE_ID = /^vendoo\.[a-z][a-z0-9-]*$/;
const SEMVER = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
const CAPABILITY = /^[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+$/;
const TYPES = new Set(['core', 'feature', 'adapter', 'extension-host']);
const STATUSES = new Set(['native', 'legacy-bridge', 'disabled']);
function uniqueStrings(values, label, pattern = CAPABILITY) {
if (!Array.isArray(values)) throw new PlatformError(`${label} muss ein Array sein.`, { code: 'MODULE_MANIFEST_INVALID' });
const normalized = values.map(value => String(value || '').trim());
if (normalized.some(value => !pattern.test(value))) {
throw new PlatformError(`${label} enthält einen ungültigen Eintrag.`, { code: 'MODULE_MANIFEST_INVALID' });
}
if (new Set(normalized).size !== normalized.length) {
throw new PlatformError(`${label} enthält Duplikate.`, { code: 'MODULE_MANIFEST_INVALID' });
}
return normalized;
}
export function validateModuleManifest(manifest) {
if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest)) {
throw new PlatformError('Modulmanifest fehlt oder ist ungültig.', { code: 'MODULE_MANIFEST_INVALID' });
}
const normalized = {
schemaVersion: Number(manifest.schemaVersion || 1),
id: String(manifest.id || '').trim(),
name: String(manifest.name || '').trim(),
version: String(manifest.version || '').trim(),
type: String(manifest.type || '').trim(),
status: String(manifest.status || 'native').trim(),
description: String(manifest.description || '').trim(),
requires: Object.freeze(uniqueStrings(manifest.requires || [], 'requires', MODULE_ID)),
permissions: Object.freeze(uniqueStrings(manifest.permissions || [], 'permissions')),
provides: Object.freeze(uniqueStrings(manifest.provides || [], 'provides')),
consumes: Object.freeze(uniqueStrings(manifest.consumes || [], 'consumes')),
owns: Object.freeze(uniqueStrings(manifest.owns || [], 'owns')),
};
if (normalized.schemaVersion !== 1) throw new PlatformError('Nicht unterstützte Manifestversion.', { code: 'MODULE_MANIFEST_VERSION' });
if (!MODULE_ID.test(normalized.id)) throw new PlatformError(`Ungültige Modul-ID: ${normalized.id}`, { code: 'MODULE_ID_INVALID' });
if (!normalized.name) throw new PlatformError(`Modulname fehlt: ${normalized.id}`, { code: 'MODULE_NAME_REQUIRED' });
if (!SEMVER.test(normalized.version)) throw new PlatformError(`Ungültige Modulversion: ${normalized.id}`, { code: 'MODULE_VERSION_INVALID' });
if (!TYPES.has(normalized.type)) throw new PlatformError(`Ungültiger Modultyp: ${normalized.id}`, { code: 'MODULE_TYPE_INVALID' });
if (!STATUSES.has(normalized.status)) throw new PlatformError(`Ungültiger Modulstatus: ${normalized.id}`, { code: 'MODULE_STATUS_INVALID' });
if (normalized.requires.includes(normalized.id)) throw new PlatformError(`Modul darf sich nicht selbst benötigen: ${normalized.id}`, { code: 'MODULE_SELF_DEPENDENCY' });
return Object.freeze(normalized);
}
@@ -1,128 +0,0 @@
import { PlatformError } from './errors.mjs';
import { validateModuleManifest } from './module-contract.mjs';
export class ModuleRegistry {
#modules = new Map();
#startOrder = [];
#ownership = new Map();
register({ manifest, lifecycle = {} }) {
const validated = validateModuleManifest(manifest);
if (this.#modules.has(validated.id)) {
throw new PlatformError(`Modul bereits registriert: ${validated.id}`, { code: 'MODULE_DUPLICATE' });
}
for (const resource of validated.owns) {
const owner = this.#ownership.get(resource);
if (owner) throw new PlatformError(`Ressource ${resource} wird bereits von ${owner} besessen.`, { code: 'MODULE_OWNERSHIP_CONFLICT' });
}
const record = {
manifest: validated,
lifecycle: {
start: typeof lifecycle.start === 'function' ? lifecycle.start : async () => {},
stop: typeof lifecycle.stop === 'function' ? lifecycle.stop : async () => {},
health: typeof lifecycle.health === 'function' ? lifecycle.health : async () => ({ ok: true }),
},
state: validated.status === 'disabled' ? 'disabled' : 'registered',
startedAt: null,
error: null,
};
this.#modules.set(validated.id, record);
for (const resource of validated.owns) this.#ownership.set(resource, validated.id);
return validated;
}
get(id) {
return this.#modules.get(id) || null;
}
#resolveStartOrder() {
const visiting = new Set();
const visited = new Set();
const order = [];
const visit = id => {
if (visited.has(id)) return;
if (visiting.has(id)) throw new PlatformError(`Zyklische Modulabhängigkeit bei ${id}.`, { code: 'MODULE_DEPENDENCY_CYCLE' });
const record = this.#modules.get(id);
if (!record) throw new PlatformError(`Fehlende Modulabhängigkeit: ${id}`, { code: 'MODULE_DEPENDENCY_MISSING' });
visiting.add(id);
for (const dependency of record.manifest.requires) visit(dependency);
visiting.delete(id);
visited.add(id);
order.push(id);
};
for (const id of this.#modules.keys()) visit(id);
const capabilities = new Set([...this.#modules.values()].flatMap(record => record.manifest.provides));
for (const record of this.#modules.values()) {
for (const capability of record.manifest.consumes) {
if (!capabilities.has(capability)) throw new PlatformError(`Fehlende Capability ${capability} für ${record.manifest.id}.`, { code: 'MODULE_CAPABILITY_MISSING' });
}
}
return order;
}
async startAll(context) {
this.#startOrder = this.#resolveStartOrder();
const started = [];
for (const id of this.#startOrder) {
const record = this.#modules.get(id);
if (record.state === 'disabled') continue;
try {
record.state = 'starting';
await record.lifecycle.start(Object.freeze({ ...context, module: record.manifest }));
record.state = 'running';
record.startedAt = new Date().toISOString();
started.push(id);
} catch (error) {
record.state = 'failed';
record.error = error?.message || String(error);
for (const startedId of started.reverse()) {
const startedRecord = this.#modules.get(startedId);
try { await startedRecord.lifecycle.stop(Object.freeze({ ...context, module: startedRecord.manifest, rollback: true })); } catch {}
startedRecord.state = 'stopped';
}
throw new PlatformError(`Modulstart fehlgeschlagen: ${id}`, { code: 'MODULE_START_FAILED', cause: error, details: { module: id } });
}
}
}
async stopAll(context) {
for (const id of [...this.#startOrder].reverse()) {
const record = this.#modules.get(id);
if (!record || record.state !== 'running') continue;
try {
record.state = 'stopping';
await record.lifecycle.stop(Object.freeze({ ...context, module: record.manifest }));
record.state = 'stopped';
} catch (error) {
record.state = 'failed';
record.error = error?.message || String(error);
}
}
}
async health() {
const checks = [];
for (const [id, record] of this.#modules) {
if (record.state === 'disabled') {
checks.push({ id, ok: true, state: 'disabled' });
continue;
}
try {
const result = await record.lifecycle.health({ module: record.manifest });
checks.push({ id, state: record.state, ok: record.state === 'running' && result?.ok !== false, ...(result || {}) });
} catch (error) {
checks.push({ id, state: record.state, ok: false, error: error?.message || String(error) });
}
}
return checks;
}
snapshot() {
return [...this.#modules.values()].map(record => ({
...record.manifest,
state: record.state,
startedAt: record.startedAt,
error: record.error,
}));
}
}
@@ -1,88 +0,0 @@
import { EventBus } from './event-bus.mjs';
import { FeatureFlagRegistry } from './feature-flags.mjs';
import { LifecycleManager } from './lifecycle.mjs';
import { ModuleRegistry } from './module-registry.mjs';
import { PolicyEngine } from './policy-engine.mjs';
import { RouteRegistry } from './route-registry.mjs';
import { loadBuiltInModules } from '../modules/catalog.mjs';
export function createPlatformKernel({ version, hasPermission }) {
const events = new EventBus();
const features = new FeatureFlagRegistry();
const modules = new ModuleRegistry();
const policies = new PolicyEngine();
const routes = new RouteRegistry({ policyEngine: policies });
const lifecycle = new LifecycleManager();
policies.register('platform.authenticated', ({ user }) => Boolean(user), {
description: 'Erfordert eine gültige Vendoo-Sitzung.',
});
policies.register('platform.security-admin', ({ user }) => Boolean(user && hasPermission(user.role, 'security.manage')), {
description: 'Erfordert die Berechtigung security.manage.',
});
policies.register('security.secrets.manage', ({ user }) => Boolean(user && hasPermission(user.role, 'security.manage')), {
owner: 'vendoo.security', description: 'Erfordert security.manage für verschlüsselte Zugangsdaten.',
});
policies.register('themes.use', ({ user }) => Boolean(user), {
owner: 'vendoo.themes', description: 'Erfordert eine gültige Sitzung für persönliche Darstellungseinstellungen.',
});
policies.register('themes.manage', ({ user }) => Boolean(user && hasPermission(user.role, 'settings.manage')), {
owner: 'vendoo.themes', description: 'Erfordert settings.manage für systemweite und eigene Theme-Profile.',
});
features.define('platform.module-kernel', { defaultValue: true, description: 'Aktiviert den modularen Plattformkernel.' });
features.define('platform.route-contracts', { defaultValue: true, description: 'Aktiviert registrierte Routenverträge.' });
features.define('security.encrypted-secret-store', { defaultValue: true, owner: 'vendoo.security', description: 'Aktiviert AES-256-GCM-verschlüsselte Zugangsdaten außerhalb der Runtime-Konfiguration.' });
features.define('security.request-telemetry', { defaultValue: true, owner: 'vendoo.security', description: 'Aktiviert Request-/Correlation-IDs und strukturierte Telemetrie.' });
features.define('security.strict-script-csp', { defaultValue: true, owner: 'vendoo.security', description: 'Blockiert Inline-Skripte und Inline-Eventhandler per CSP.' });
features.define('themes.token-runtime', { defaultValue: true, owner: 'vendoo.themes', description: 'Aktiviert den versionierten Design-Token-Vertrag.' });
features.define('themes.manager', { defaultValue: true, owner: 'vendoo.themes', description: 'Aktiviert den sicheren Theme Manager mit Benutzerpräferenzen.' });
features.define('themes.accessibility-gate', { defaultValue: true, owner: 'vendoo.themes', description: 'Prüft Theme-Kontraste und sichere Tokenwerte.' });
features.define('extensions.isolated-host', { defaultValue: false, owner: 'vendoo.security', description: 'Reserviert für einen späteren isolierten Extension-Host.' });
for (const module of loadBuiltInModules()) modules.register(module);
lifecycle.register({
id: 'modules',
order: 20,
start: context => modules.startAll(context),
stop: context => modules.stopAll(context),
});
const context = Object.freeze({ version, events, features, policies });
return Object.freeze({
version,
events,
features,
lifecycle,
modules,
policies,
routes,
async start() {
await lifecycle.start(context);
await events.emit('platform.started', { version }, { owner: 'vendoo.system' });
},
async stop() {
await events.emit('platform.stopping', { version }, { owner: 'vendoo.system' });
await lifecycle.stop(context);
},
async health() {
const moduleChecks = await modules.health();
return {
ok: lifecycle.snapshot().state === 'running' && moduleChecks.every(check => check.ok),
lifecycle: lifecycle.snapshot(),
modules: moduleChecks,
};
},
snapshot() {
return {
version,
architecture: 'modular-monolith',
lifecycle: lifecycle.snapshot(),
modules: modules.snapshot(),
features: features.list(),
policies: policies.list(),
routes: routes.list(),
};
},
});
}
@@ -1,30 +0,0 @@
import { PlatformError } from './errors.mjs';
const POLICY_ID = /^[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+$/;
export class PolicyEngine {
#policies = new Map();
register(id, evaluator, { owner = 'vendoo.security', description = '' } = {}) {
const normalized = String(id || '');
if (!POLICY_ID.test(normalized)) throw new PlatformError(`Ungültige Policy-ID: ${normalized}`, { code: 'POLICY_ID_INVALID' });
if (this.#policies.has(normalized)) throw new PlatformError(`Policy bereits registriert: ${normalized}`, { code: 'POLICY_DUPLICATE' });
if (typeof evaluator !== 'function') throw new PlatformError(`Policy benötigt eine Prüffunktion: ${normalized}`, { code: 'POLICY_EVALUATOR_INVALID' });
this.#policies.set(normalized, { id: normalized, evaluator, owner, description });
}
async evaluate(id, context) {
const policy = this.#policies.get(id);
if (!policy) {
return { allowed: false, reason: 'policy_not_registered', policy: id };
}
const result = await policy.evaluator(Object.freeze({ ...context }));
if (result === true) return { allowed: true, policy: id };
if (result === false || result == null) return { allowed: false, reason: 'denied', policy: id };
return { allowed: Boolean(result.allowed), reason: result.reason || null, policy: id, details: result.details || null };
}
list() {
return [...this.#policies.values()].map(({ evaluator: _evaluator, ...policy }) => ({ ...policy }));
}
}
@@ -1,64 +0,0 @@
import { PlatformError, platformErrorPayload } from './errors.mjs';
const METHODS = new Set(['get', 'post', 'put', 'patch', 'delete']);
const ROUTE_ID = /^[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+$/;
export class RouteRegistry {
#routes = new Map();
#policyEngine;
constructor({ policyEngine }) {
this.#policyEngine = policyEngine;
}
register(app, definition) {
const method = String(definition.method || '').toLowerCase();
const id = String(definition.id || '');
const path = String(definition.path || '');
if (!ROUTE_ID.test(id)) throw new PlatformError(`Ungültige Route-ID: ${id}`, { code: 'ROUTE_ID_INVALID' });
if (!METHODS.has(method)) throw new PlatformError(`Ungültige HTTP-Methode für ${id}.`, { code: 'ROUTE_METHOD_INVALID' });
if (!path.startsWith('/')) throw new PlatformError(`Ungültiger Routenpfad für ${id}.`, { code: 'ROUTE_PATH_INVALID' });
if (!definition.policy) throw new PlatformError(`Route ${id} benötigt eine explizite Policy.`, { code: 'ROUTE_POLICY_REQUIRED' });
if (!definition.owner) throw new PlatformError(`Route ${id} benötigt einen Modulbesitzer.`, { code: 'ROUTE_OWNER_REQUIRED' });
if (typeof definition.handler !== 'function') throw new PlatformError(`Route ${id} benötigt einen Handler.`, { code: 'ROUTE_HANDLER_REQUIRED' });
const key = `${method.toUpperCase()} ${path}`;
if (this.#routes.has(key)) throw new PlatformError(`Route bereits registriert: ${key}`, { code: 'ROUTE_DUPLICATE' });
const contract = Object.freeze({
id,
method: method.toUpperCase(),
path,
owner: String(definition.owner),
policy: String(definition.policy),
audit: String(definition.audit || ''),
input: definition.input ? 'validated' : 'none',
rateLimit: String(definition.rateLimit || 'default'),
csrf: definition.csrf !== false,
stability: String(definition.stability || 'internal'),
});
this.#routes.set(key, contract);
app[method](path, ...(definition.middleware || []), async (req, res, next) => {
try {
const decision = await this.#policyEngine.evaluate(contract.policy, { req, user: req.user, route: contract });
if (!decision.allowed) {
throw new PlatformError('Keine Berechtigung für diese Aktion.', {
code: 'POLICY_DENIED', status: 403, expose: true,
details: { policy: contract.policy, reason: decision.reason },
});
}
if (typeof definition.input === 'function') req.validatedBody = definition.input(req.body);
await definition.handler(req, res, { route: contract, decision });
} catch (error) {
if (res.headersSent) return next(error);
const status = Number.isInteger(error?.status) ? error.status : 500;
res.status(status).json(platformErrorPayload(error, req.requestId));
}
});
return contract;
}
list() {
return [...this.#routes.values()].map(route => ({ ...route }));
}
}
@@ -1,28 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.ai",
"name": "AI Services",
"version": "1.0.0",
"type": "feature",
"status": "legacy-bridge",
"description": "Vertrag für den bestehenden Vendoo-Bereich AI Services; schrittweise Migration ohne Funktionsbruch.",
"requires": [
"vendoo.security",
"vendoo.media"
],
"permissions": [
"generation.execute"
],
"provides": [
"ai.text",
"ai.images"
],
"consumes": [
"media.assets",
"security.policies"
],
"owns": [
"ai.providers",
"ai.jobs"
]
}
@@ -1,26 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.auth",
"name": "Authentication",
"version": "1.0.0",
"type": "core",
"status": "legacy-bridge",
"description": "Vertrag für den bestehenden Vendoo-Bereich Authentication; schrittweise Migration ohne Funktionsbruch.",
"requires": [
"vendoo.security"
],
"permissions": [
"sessions.manage"
],
"provides": [
"auth.sessions",
"auth.identity"
],
"consumes": [
"security.policies"
],
"owns": [
"auth.sessions",
"auth.tokens"
]
}
@@ -1,23 +0,0 @@
import { readFileSync } from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import { createThemesModule } from './themes/index.mjs';
import { createSecurityModule } from './security/index.mjs';
const here = dirname(fileURLToPath(import.meta.url));
const moduleNames = ['system', 'auth', 'users', 'media', 'listings', 'ai', 'flux-studio', 'quality', 'publishing', 'operations'];
function legacyModule(name) {
return {
manifest: JSON.parse(readFileSync(join(here, name, 'module.json'), 'utf8')),
lifecycle: {
async start() {},
async stop() {},
async health() { return { ok: true, bridge: 'legacy' }; },
},
};
}
export function loadBuiltInModules() {
return [...moduleNames.map(legacyModule), createSecurityModule(), createThemesModule()];
}
@@ -1,25 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.flux-studio",
"name": "FLUX Studio",
"version": "1.0.0",
"type": "feature",
"status": "legacy-bridge",
"description": "Vertrag für den bestehenden Vendoo-Bereich FLUX Studio; schrittweise Migration ohne Funktionsbruch.",
"requires": [
"vendoo.ai"
],
"permissions": [
"generation.execute"
],
"provides": [
"flux.prompt-jobs"
],
"consumes": [
"ai.images"
],
"owns": [
"flux.generations",
"flux.history"
]
}
@@ -1,31 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.listings",
"name": "Listings & Inventory",
"version": "1.0.0",
"type": "feature",
"status": "legacy-bridge",
"description": "Vertrag für den bestehenden Vendoo-Bereich Listings & Inventory; schrittweise Migration ohne Funktionsbruch.",
"requires": [
"vendoo.auth",
"vendoo.media"
],
"permissions": [
"listings.view",
"listings.edit",
"listings.delete",
"inventory.edit"
],
"provides": [
"listings.catalog",
"inventory.stock"
],
"consumes": [
"media.assets",
"auth.identity"
],
"owns": [
"listings.records",
"inventory.locations"
]
}
@@ -1,28 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.media",
"name": "Media Library",
"version": "1.0.0",
"type": "feature",
"status": "legacy-bridge",
"description": "Vertrag für den bestehenden Vendoo-Bereich Media Library; schrittweise Migration ohne Funktionsbruch.",
"requires": [
"vendoo.auth"
],
"permissions": [
"media.view",
"media.edit",
"media.delete"
],
"provides": [
"media.assets",
"media.derivatives"
],
"consumes": [
"auth.identity"
],
"owns": [
"media.library",
"media.uploads"
]
}
@@ -1,26 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.operations",
"name": "Operations Center",
"version": "1.0.0",
"type": "feature",
"status": "legacy-bridge",
"description": "Vertrag für den bestehenden Vendoo-Bereich Operations Center; schrittweise Migration ohne Funktionsbruch.",
"requires": [
"vendoo.security"
],
"permissions": [
"operations.manage"
],
"provides": [
"operations.backup",
"operations.update"
],
"consumes": [
"security.audit"
],
"owns": [
"operations.backups",
"operations.updates"
]
}
@@ -1,30 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.publishing",
"name": "Publishing",
"version": "1.0.0",
"type": "feature",
"status": "legacy-bridge",
"description": "Vertrag für den bestehenden Vendoo-Bereich Publishing; schrittweise Migration ohne Funktionsbruch.",
"requires": [
"vendoo.listings",
"vendoo.security"
],
"permissions": [
"publishing.view",
"publishing.execute",
"publishing.manage"
],
"provides": [
"publishing.jobs",
"publishing.adapters"
],
"consumes": [
"listings.catalog",
"security.policies"
],
"owns": [
"publishing.queue",
"publishing.events"
]
}
@@ -1,26 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.quality",
"name": "Quality Center",
"version": "1.0.0",
"type": "feature",
"status": "legacy-bridge",
"description": "Vertrag für den bestehenden Vendoo-Bereich Quality Center; schrittweise Migration ohne Funktionsbruch.",
"requires": [
"vendoo.listings",
"vendoo.ai"
],
"permissions": [
"quality.execute"
],
"provides": [
"quality.reports"
],
"consumes": [
"listings.catalog",
"ai.text"
],
"owns": [
"quality.history"
]
}
@@ -1,26 +0,0 @@
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { secretStoreStatus } from '../../../lib/secret-store.mjs';
import { getRequestTelemetry } from '../../../lib/structured-logger.mjs';
const here = dirname(fileURLToPath(import.meta.url));
const manifest = JSON.parse(readFileSync(join(here, 'module.json'), 'utf8'));
export function createSecurityModule() {
return {
manifest,
lifecycle: {
async start() {},
async stop() {},
async health() {
const secrets = secretStoreStatus();
return { ok: true, provider: secrets.provider, encrypted_secrets: secrets.encrypted };
},
},
};
}
export function getSecurityFoundationStatus() {
return { secrets: secretStoreStatus(), requests: getRequestTelemetry() };
}
@@ -1,31 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.security",
"name": "Security Core",
"version": "2.0.0",
"type": "core",
"status": "native",
"description": "Nativer Sicherheitskern für verschlüsselte Secrets, Request-Telemetrie, Sicherheitsheader und Security-Dashboard.",
"requires": [
"vendoo.system"
],
"permissions": [
"security.manage"
],
"provides": [
"security.policies",
"security.audit",
"security.secrets",
"security.telemetry",
"security.headers"
],
"consumes": [
"platform.events"
],
"owns": [
"security.permissions",
"security.rate-limits",
"security.secret-store",
"security.request-telemetry"
]
}
@@ -1,23 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.system",
"name": "System Kernel",
"version": "1.0.0",
"type": "core",
"status": "legacy-bridge",
"description": "Vertrag für den bestehenden Vendoo-Bereich System Kernel; schrittweise Migration ohne Funktionsbruch.",
"requires": [],
"permissions": [
"dashboard.view"
],
"provides": [
"platform.lifecycle",
"platform.events",
"platform.features"
],
"consumes": [],
"owns": [
"system.runtime",
"system.health"
]
}
@@ -1,27 +0,0 @@
import { readFileSync } from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import { PlatformError } from '../../kernel/errors.mjs';
const here = dirname(fileURLToPath(import.meta.url));
const manifest = JSON.parse(readFileSync(join(here, 'module.json'), 'utf8'));
let service = null;
export function getThemeService() {
if (!service) throw new PlatformError('Theme-Modul ist noch nicht gestartet.', { code: 'THEME_MODULE_NOT_READY', status: 503, expose: true });
return service;
}
export function createThemesModule() {
return {
manifest,
lifecycle: {
async start() {
const { createThemeService } = await import('./service.mjs');
service = createThemeService();
},
async stop() { service = null; },
async health() { return getThemeService().health(); },
},
};
}
@@ -1,21 +0,0 @@
CREATE TABLE IF NOT EXISTS theme_profiles (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
base_theme TEXT NOT NULL DEFAULT 'light',
values_json TEXT NOT NULL DEFAULT '{}',
created_by INTEGER,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY(created_by) REFERENCES users(id) ON DELETE SET NULL
);
CREATE TABLE IF NOT EXISTS user_theme_preferences (
user_id INTEGER PRIMARY KEY,
theme_id TEXT NOT NULL DEFAULT 'inherit',
density TEXT NOT NULL DEFAULT 'comfortable',
reduced_motion TEXT NOT NULL DEFAULT 'system',
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_theme_profiles_updated ON theme_profiles(updated_at DESC);
@@ -1,30 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.themes",
"name": "Themes & Design System",
"version": "1.1.0",
"type": "feature",
"status": "native",
"description": "Natives Theme- und Design-System-Modul mit sicherem Token-Editor, Benutzerpräferenzen und Accessibility-Prüfungen.",
"requires": [
"vendoo.system"
],
"permissions": [
"settings.manage",
"themes.use"
],
"provides": [
"themes.tokens",
"themes.runtime",
"themes.profiles",
"themes.accessibility"
],
"consumes": [
"platform.events"
],
"owns": [
"themes.definitions",
"themes.user-preferences",
"themes.system-default"
]
}
@@ -1,95 +0,0 @@
import { readFileSync } from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import { db } from '../../../lib/db.mjs';
const here = dirname(fileURLToPath(import.meta.url));
const migrationSql = readFileSync(join(here, 'migrations', '001_theme_profiles.sql'), 'utf8');
export function ensureThemeSchema() {
db.exec(migrationSql);
}
function parseProfile(row) {
if (!row) return null;
let values = {};
try { values = JSON.parse(row.values_json || '{}'); } catch {}
return { ...row, values };
}
export function listThemeProfiles() {
ensureThemeSchema();
return db.prepare('SELECT * FROM theme_profiles ORDER BY name COLLATE NOCASE, id').all().map(parseProfile);
}
export function getThemeProfile(id) {
ensureThemeSchema();
return parseProfile(db.prepare('SELECT * FROM theme_profiles WHERE id = ?').get(id));
}
export function saveThemeProfile(profile, userId) {
ensureThemeSchema();
db.prepare(`INSERT INTO theme_profiles (id, name, base_theme, values_json, created_by)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET name = excluded.name, base_theme = excluded.base_theme,
values_json = excluded.values_json, updated_at = datetime('now')`).run(
profile.id, profile.name, profile.base_theme, JSON.stringify(profile.values || {}), userId || null,
);
return getThemeProfile(profile.id);
}
export function deleteThemeProfile(id) {
ensureThemeSchema();
const transaction = db.transaction(() => {
db.prepare("UPDATE user_theme_preferences SET theme_id = 'inherit', updated_at = datetime('now') WHERE theme_id = ?").run(id);
const system = db.prepare("SELECT value FROM settings WHERE key = 'theme_system_default'").get();
if (system?.value === id) db.prepare("INSERT OR REPLACE INTO settings (key, value) VALUES ('theme_system_default', 'system')").run();
return db.prepare('DELETE FROM theme_profiles WHERE id = ?').run(id).changes;
});
return transaction();
}
export function getUserThemePreference(userId) {
ensureThemeSchema();
return db.prepare('SELECT theme_id, density, reduced_motion, updated_at FROM user_theme_preferences WHERE user_id = ?').get(userId) || {
theme_id: 'inherit', density: 'comfortable', reduced_motion: 'system', updated_at: null,
};
}
export function saveUserThemePreference(userId, preference) {
ensureThemeSchema();
db.prepare(`INSERT INTO user_theme_preferences (user_id, theme_id, density, reduced_motion)
VALUES (?, ?, ?, ?)
ON CONFLICT(user_id) DO UPDATE SET theme_id = excluded.theme_id, density = excluded.density,
reduced_motion = excluded.reduced_motion, updated_at = datetime('now')`).run(
userId, preference.theme_id, preference.density, preference.reduced_motion,
);
return getUserThemePreference(userId);
}
function getSetting(key, fallback) {
const row = db.prepare('SELECT value FROM settings WHERE key = ?').get(key);
return row?.value ?? fallback;
}
function setSetting(key, value) {
db.prepare('INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)').run(key, String(value));
}
export function getThemeSystemDefault() {
return {
theme_id: getSetting('theme_system_default', 'system'),
density: getSetting('theme_system_density', 'comfortable'),
reduced_motion: getSetting('theme_system_reduced_motion', 'system'),
};
}
export function saveThemeSystemDefault(preference) {
const transaction = db.transaction(() => {
setSetting('theme_system_default', preference.theme_id);
setSetting('theme_system_density', preference.density);
setSetting('theme_system_reduced_motion', preference.reduced_motion);
});
transaction();
return getThemeSystemDefault();
}
@@ -1,85 +0,0 @@
import { PlatformError } from '../../kernel/errors.mjs';
import {
evaluateThemeAccessibility, getBaseThemeValues, getBuiltinThemes, getThemeContract,
resolveThemeValues, validateThemeDefinition, validateThemePreference,
} from '../../core/themes/theme-contract.mjs';
import {
deleteThemeProfile, ensureThemeSchema, getThemeProfile, getThemeSystemDefault,
getUserThemePreference, listThemeProfiles, saveThemeProfile, saveThemeSystemDefault,
saveUserThemePreference,
} from './repository.mjs';
function decorate(profile) {
return {
...profile,
builtin: false,
resolved_values: resolveThemeValues({ baseTheme: profile.base_theme, values: profile.values }),
accessibility: evaluateThemeAccessibility({ baseTheme: profile.base_theme, values: profile.values }),
};
}
function customExists(id) {
return Boolean(getThemeProfile(id));
}
function effectivePreference(userPreference, systemDefault) {
return userPreference.theme_id === 'inherit' ? { ...systemDefault, inherited: true } : { ...userPreference, inherited: false };
}
export function createThemeService() {
ensureThemeSchema();
return Object.freeze({
health() {
ensureThemeSchema();
return { ok: true, profiles: listThemeProfiles().length, contract: getThemeContract().contractVersion };
},
catalog(userId) {
const custom = listThemeProfiles().map(decorate);
const preference = getUserThemePreference(userId);
const systemDefault = getThemeSystemDefault();
return {
contract: getThemeContract(),
builtin: getBuiltinThemes(),
custom,
preference,
system_default: systemDefault,
effective_preference: effectivePreference(preference, systemDefault),
};
},
validate(input) {
const theme = validateThemeDefinition(input, { allowExistingId: true });
return { theme, resolved_values: resolveThemeValues({ baseTheme: theme.base_theme, values: theme.values }), accessibility: theme.accessibility };
},
create(input, userId) {
const theme = validateThemeDefinition(input);
if (getThemeProfile(theme.id)) throw new PlatformError('Theme-ID ist bereits vorhanden.', { code: 'THEME_DUPLICATE', status: 409, expose: true });
return decorate(saveThemeProfile(theme, userId));
},
update(id, input, userId) {
if (!getThemeProfile(id)) throw new PlatformError('Theme wurde nicht gefunden.', { code: 'THEME_NOT_FOUND', status: 404, expose: true });
const theme = validateThemeDefinition({ ...input, id }, { allowExistingId: true });
return decorate(saveThemeProfile(theme, userId));
},
remove(id) {
if (!getThemeProfile(id)) throw new PlatformError('Theme wurde nicht gefunden.', { code: 'THEME_NOT_FOUND', status: 404, expose: true });
deleteThemeProfile(id);
return { ok: true, id };
},
saveUserPreference(userId, input) {
const preference = validateThemePreference(input, { customThemeExists: customExists });
return saveUserThemePreference(userId, preference);
},
saveSystemDefault(input) {
const preference = validateThemePreference(input, { customThemeExists: customExists });
if (preference.theme_id === 'inherit') throw new PlatformError('Der Systemstandard kann nicht auf „Vererben“ gesetzt werden.', { code: 'THEME_SYSTEM_INHERIT_INVALID', status: 400, expose: true });
return saveThemeSystemDefault(preference);
},
exportTheme(id) {
const profile = getThemeProfile(id);
if (!profile) throw new PlatformError('Theme wurde nicht gefunden.', { code: 'THEME_NOT_FOUND', status: 404, expose: true });
return { schemaVersion: 1, type: 'vendoo-theme', theme: { id: profile.id, name: profile.name, base_theme: profile.base_theme, values: profile.values } };
},
});
}
export { getBaseThemeValues };
@@ -1,26 +0,0 @@
{
"schemaVersion": 1,
"id": "vendoo.users",
"name": "Users & Roles",
"version": "1.0.0",
"type": "feature",
"status": "legacy-bridge",
"description": "Vertrag für den bestehenden Vendoo-Bereich Users & Roles; schrittweise Migration ohne Funktionsbruch.",
"requires": [
"vendoo.auth"
],
"permissions": [
"users.manage"
],
"provides": [
"users.directory",
"users.roles"
],
"consumes": [
"auth.identity"
],
"owns": [
"users.accounts",
"users.preferences"
]
}
@@ -1,30 +0,0 @@
import dotenv from 'dotenv';
import { existsSync } from 'node:fs';
import { dirname, isAbsolute, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const appRoot = dirname(fileURLToPath(import.meta.url));
const rootEnvPath = join(appRoot, '.env');
// Lokaler Windows-/Entwicklungsbetrieb: klassische .env zuerst laden.
if (existsSync(rootEnvPath)) dotenv.config({ path: rootEnvPath, override: false });
// Docker/NAS/VPS: schreibbarer persistenter Overlay-Speicher für Eingabemasken.
const configuredPath = String(process.env.VENDOO_CONFIG_PATH || '').trim();
const defaultPath = process.env.VENDOO_DATA_DIR
? join(String(process.env.VENDOO_DATA_DIR), 'config', 'vendoo.env')
: rootEnvPath;
const configCandidate = configuredPath || defaultPath;
const runtimeConfigPath = resolve(isAbsolute(configCandidate) ? configCandidate : join(appRoot, configCandidate));
process.env.VENDOO_CONFIG_PATH = runtimeConfigPath;
if (runtimeConfigPath !== rootEnvPath && existsSync(runtimeConfigPath)) {
dotenv.config({ path: runtimeConfigPath, override: true });
}
const { hydrateSecretsToEnvironment, migrateRuntimeConfigSecrets } = await import('./lib/secret-store.mjs');
const migration = migrateRuntimeConfigSecrets();
if (migration.migrated.length) console.log(`Security: ${migration.migrated.length} Secrets aus der Runtime-Konfiguration verschlüsselt migriert.`);
hydrateSecretsToEnvironment();
await import('./server.mjs');
@@ -1,11 +0,0 @@
# Optionaler Override für NAS-Bind-Mounts.
# Vorher ./runtime/{db,uploads,backups,operations,logs} anlegen und UID/GID 1000 Schreibrechte geben.
services:
vendoo:
volumes:
- ./runtime/db:/app/data/db
- ./runtime/uploads:/app/data/uploads
- ./runtime/backups:/app/data/backups
- ./runtime/operations:/app/data/operations
- ./runtime/logs:/app/data/logs
- ./runtime/config:/app/data/config
@@ -1,106 +0,0 @@
name: vendoo
services:
vendoo:
build:
context: .
dockerfile: Dockerfile
image: vendoo:1.37.0
container_name: vendoo
restart: unless-stopped
init: true
env_file:
- .env
environment:
NODE_ENV: production
PORT: 8124
VENDOO_BIND_HOST: 0.0.0.0
VENDOO_TRUST_PROXY: "true"
VENDOO_COOKIE_SECURE: "true"
VENDOO_DATA_DIR: /app/data
VENDOO_DB_PATH: /app/data/db/vendoo.db
VENDOO_UPLOADS_DIR: /app/data/uploads
VENDOO_BACKUP_DIR: /app/data/backups
VENDOO_OPERATIONS_DIR: /app/data/operations
VENDOO_LOG_DIR: /app/data/logs
VENDOO_CONFIG_PATH: /app/data/config/vendoo.env
VENDOO_REQUIRE_SETUP_TOKEN: "true"
LOCAL_IMAGE_ENABLED: "${LOCAL_IMAGE_ENABLED:-false}"
expose:
- "8124"
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- vendoo_db:/app/data/db
- vendoo_uploads:/app/data/uploads
- vendoo_backups:/app/data/backups
- vendoo_operations:/app/data/operations
- vendoo_logs:/app/data/logs
- vendoo_config:/app/data/config
read_only: true
tmpfs:
- /tmp:size=512m,mode=1777
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
pids_limit: 256
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
stop_grace_period: 15s
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:8124/readyz').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"]
interval: 30s
timeout: 5s
start_period: 30s
retries: 3
networks:
- vendoo
caddy:
image: caddy:2-alpine
container_name: vendoo-caddy
restart: unless-stopped
depends_on:
vendoo:
condition: service_healthy
environment:
VENDOO_DOMAIN: "${VENDOO_DOMAIN}"
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./deploy/Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
pids_limit: 128
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
networks:
- vendoo
networks:
vendoo:
driver: bridge
volumes:
vendoo_db:
vendoo_uploads:
vendoo_backups:
vendoo_operations:
vendoo_logs:
vendoo_config:
caddy_data:
caddy_config:
@@ -1,72 +0,0 @@
name: vendoo
services:
vendoo:
build:
context: .
dockerfile: Dockerfile
image: vendoo:1.37.0
container_name: vendoo
restart: unless-stopped
init: true
env_file:
- .env
environment:
NODE_ENV: production
PORT: 8124
VENDOO_BIND_HOST: 0.0.0.0
VENDOO_DATA_DIR: /app/data
VENDOO_DB_PATH: /app/data/db/vendoo.db
VENDOO_UPLOADS_DIR: /app/data/uploads
VENDOO_BACKUP_DIR: /app/data/backups
VENDOO_OPERATIONS_DIR: /app/data/operations
VENDOO_LOG_DIR: /app/data/logs
VENDOO_CONFIG_PATH: /app/data/config/vendoo.env
VENDOO_REQUIRE_SETUP_TOKEN: "true"
LOCAL_IMAGE_ENABLED: "${LOCAL_IMAGE_ENABLED:-false}"
ports:
- "${VENDOO_PUBLISH_ADDRESS:-127.0.0.1}:${VENDOO_HOST_PORT:-8124}:8124"
expose:
- "8124"
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- vendoo_db:/app/data/db
- vendoo_uploads:/app/data/uploads
- vendoo_backups:/app/data/backups
- vendoo_operations:/app/data/operations
- vendoo_logs:/app/data/logs
- vendoo_config:/app/data/config
read_only: true
tmpfs:
- /tmp:size=512m,mode=1777
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
pids_limit: 256
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
stop_grace_period: 15s
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:8124/readyz').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"]
interval: 30s
timeout: 5s
start_period: 30s
retries: 3
networks:
- vendoo
networks:
vendoo:
driver: bridge
volumes:
vendoo_db:
vendoo_uploads:
vendoo_backups:
vendoo_operations:
vendoo_logs:
vendoo_config:
@@ -1,278 +0,0 @@
CREATE TABLE IF NOT EXISTS listings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
platform TEXT NOT NULL,
ai_provider TEXT NOT NULL,
title TEXT,
description TEXT,
description_html TEXT,
tags TEXT,
photos TEXT,
seller_notes TEXT,
brand TEXT,
category TEXT,
size TEXT,
color TEXT,
condition TEXT,
price REAL,
status TEXT DEFAULT 'active',
language TEXT DEFAULT 'de',
created_by INTEGER,
updated_by INTEGER,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT
);
CREATE TABLE IF NOT EXISTS templates (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
platform TEXT,
seller_notes TEXT,
language TEXT DEFAULT 'de',
default_tags TEXT,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT
);
CREATE TABLE IF NOT EXISTS publish_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
listing_id INTEGER NOT NULL,
platform TEXT NOT NULL,
status TEXT DEFAULT 'pending',
external_id TEXT,
external_url TEXT,
offer_id TEXT,
sync_status TEXT,
last_synced_at TEXT,
ended_at TEXT,
updated_at TEXT,
published_at TEXT,
created_at TEXT DEFAULT (datetime('now')),
FOREIGN KEY (listing_id) REFERENCES listings(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_publish_log_external ON publish_log(platform, external_id);
INSERT OR IGNORE INTO settings (key, value) VALUES ('default_platform', 'vinted');
INSERT OR IGNORE INTO settings (key, value) VALUES ('default_ai', 'claude');
INSERT OR IGNORE INTO settings (key, value) VALUES ('seller_notes', '');
INSERT OR IGNORE INTO settings (key, value) VALUES ('default_language', 'de');
CREATE TABLE IF NOT EXISTS mobile_upload_sessions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
token_hash TEXT NOT NULL UNIQUE,
user_id INTEGER,
listing_id INTEGER,
context TEXT NOT NULL DEFAULT 'generator',
files TEXT NOT NULL DEFAULT '[]',
status TEXT NOT NULL DEFAULT 'active',
expires_at TEXT NOT NULL,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_mobile_upload_token ON mobile_upload_sessions(token_hash);
CREATE INDEX IF NOT EXISTS idx_mobile_upload_expires ON mobile_upload_sessions(expires_at);
INSERT OR IGNORE INTO settings (key, value) VALUES ('ai_model_photos_enabled', '1');
INSERT OR IGNORE INTO settings (key, value) VALUES ('ai_model_photo_default_variants', '1');
INSERT OR IGNORE INTO settings (key, value) VALUES ('ai_model_photo_default_preset', 'mixed');
INSERT OR IGNORE INTO settings (key, value) VALUES ('ai_model_photo_block_underwear', '1');
INSERT OR IGNORE INTO settings (key, value) VALUES ('ai_model_photo_block_kids', '1');
INSERT OR IGNORE INTO settings (key, value) VALUES ('ai_model_photo_provider', 'openai');
CREATE TABLE IF NOT EXISTS ai_model_generations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
listing_id INTEGER,
context TEXT NOT NULL DEFAULT 'generator',
preset TEXT NOT NULL,
variants INTEGER NOT NULL DEFAULT 3,
source_photos TEXT NOT NULL DEFAULT '[]',
generated_photos TEXT NOT NULL DEFAULT '[]',
prompt_summary TEXT,
moderation_notes TEXT,
safety_status TEXT NOT NULL DEFAULT 'pending',
status TEXT NOT NULL DEFAULT 'pending',
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT,
FOREIGN KEY (listing_id) REFERENCES listings(id) ON DELETE SET NULL
);
CREATE INDEX IF NOT EXISTS idx_ai_model_generations_listing ON ai_model_generations(listing_id);
CREATE TABLE IF NOT EXISTS ai_model_photos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
generation_id INTEGER NOT NULL,
listing_id INTEGER,
variant_index INTEGER NOT NULL DEFAULT 1,
preset TEXT NOT NULL,
image_path TEXT NOT NULL,
source_photo TEXT,
prompt TEXT,
moderation_result TEXT,
safety_status TEXT NOT NULL DEFAULT 'pending',
created_at TEXT DEFAULT (datetime('now')),
FOREIGN KEY (generation_id) REFERENCES ai_model_generations(id) ON DELETE CASCADE,
FOREIGN KEY (listing_id) REFERENCES listings(id) ON DELETE SET NULL
);
CREATE INDEX IF NOT EXISTS idx_ai_model_photos_listing ON ai_model_photos(listing_id);
CREATE TABLE IF NOT EXISTS flux_images (
id INTEGER PRIMARY KEY AUTOINCREMENT,
prompt TEXT NOT NULL,
image_path TEXT NOT NULL UNIQUE,
width INTEGER,
height INTEGER,
seed INTEGER,
steps INTEGER,
style TEXT DEFAULT 'none',
edited_from INTEGER,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_flux_images_created ON flux_images(created_at DESC);
CREATE TABLE IF NOT EXISTS quality_reports (
id INTEGER PRIMARY KEY AUTOINCREMENT,
listing_id INTEGER NOT NULL,
score INTEGER NOT NULL DEFAULT 0,
grade TEXT NOT NULL DEFAULT 'E',
ready INTEGER NOT NULL DEFAULT 0,
blockers INTEGER NOT NULL DEFAULT 0,
warnings INTEGER NOT NULL DEFAULT 0,
recommendations INTEGER NOT NULL DEFAULT 0,
report_json TEXT NOT NULL DEFAULT '{}',
analyzed_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY(listing_id) REFERENCES listings(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_quality_reports_listing ON quality_reports(listing_id, id DESC);
CREATE INDEX IF NOT EXISTS idx_quality_reports_score ON quality_reports(score, analyzed_at DESC);
CREATE TABLE IF NOT EXISTS publishing_jobs (
id TEXT PRIMARY KEY,
listing_id INTEGER NOT NULL,
platform TEXT NOT NULL,
mode TEXT NOT NULL DEFAULT 'api',
action TEXT NOT NULL DEFAULT 'publish',
status TEXT NOT NULL DEFAULT 'queued',
phase TEXT NOT NULL DEFAULT 'queued',
idempotency_key TEXT NOT NULL UNIQUE,
external_id TEXT,
external_url TEXT,
offer_id TEXT,
retries INTEGER NOT NULL DEFAULT 0,
max_retries INTEGER NOT NULL DEFAULT 3,
next_attempt_at TEXT,
claimed_by TEXT,
claimed_at TEXT,
error_code TEXT,
error_message TEXT,
payload_json TEXT NOT NULL DEFAULT '{}',
result_json TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL DEFAULT (datetime('now')),
started_at TEXT,
completed_at TEXT,
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY(listing_id) REFERENCES listings(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_publishing_jobs_status ON publishing_jobs(status, next_attempt_at, created_at);
CREATE INDEX IF NOT EXISTS idx_publishing_jobs_listing ON publishing_jobs(listing_id, platform, created_at DESC);
CREATE TABLE IF NOT EXISTS publishing_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
job_id TEXT,
listing_id INTEGER NOT NULL,
platform TEXT NOT NULL,
level TEXT NOT NULL DEFAULT 'info',
event_type TEXT NOT NULL,
message TEXT NOT NULL,
details_json TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY(job_id) REFERENCES publishing_jobs(id) ON DELETE SET NULL,
FOREIGN KEY(listing_id) REFERENCES listings(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_publishing_events_job ON publishing_events(job_id, id DESC);
CREATE INDEX IF NOT EXISTS idx_publishing_events_listing ON publishing_events(listing_id, id DESC);
-- Mehrbenutzer- und Sicherheitsgrundlage 1.31.0
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL DEFAULT '',
password_hash TEXT,
role TEXT NOT NULL DEFAULT 'editor',
active INTEGER NOT NULL DEFAULT 1,
avatar_color TEXT,
last_active_at TEXT,
failed_login_count INTEGER NOT NULL DEFAULT 0,
locked_until TEXT,
password_changed_at TEXT,
created_at TEXT DEFAULT (datetime('now')),
invited_by INTEGER
);
CREATE TABLE IF NOT EXISTS sessions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
token_hash TEXT UNIQUE NOT NULL,
ip TEXT,
user_agent TEXT,
expires_at TEXT NOT NULL,
last_seen_at TEXT,
revoked_at TEXT,
created_at TEXT DEFAULT (datetime('now')),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS audit_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
user_email TEXT,
action TEXT NOT NULL,
target_type TEXT,
target_id TEXT,
details TEXT,
ip TEXT,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS resource_locks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
resource_type TEXT NOT NULL,
resource_id TEXT NOT NULL,
user_id INTEGER NOT NULL,
token_hash TEXT NOT NULL UNIQUE,
acquired_at TEXT NOT NULL DEFAULT (datetime('now')),
renewed_at TEXT NOT NULL DEFAULT (datetime('now')),
expires_at TEXT NOT NULL,
client_label TEXT,
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
UNIQUE(resource_type, resource_id)
);
CREATE INDEX IF NOT EXISTS idx_resource_locks_expiry ON resource_locks(expires_at);
CREATE INDEX IF NOT EXISTS idx_resource_locks_user ON resource_locks(user_id, expires_at);
-- Natives Theme-Modul 1.36.0
CREATE TABLE IF NOT EXISTS theme_profiles (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
base_theme TEXT NOT NULL DEFAULT 'light',
values_json TEXT NOT NULL DEFAULT '{}',
created_by INTEGER,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY(created_by) REFERENCES users(id) ON DELETE SET NULL
);
CREATE TABLE IF NOT EXISTS user_theme_preferences (
user_id INTEGER PRIMARY KEY,
theme_id TEXT NOT NULL DEFAULT 'inherit',
density TEXT NOT NULL DEFAULT 'comfortable',
reduced_motion TEXT NOT NULL DEFAULT 'system',
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_theme_profiles_updated ON theme_profiles(updated_at DESC);
@@ -1,16 +0,0 @@
{
admin off
}
{$VENDOO_DOMAIN} {
encode zstd gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options "nosniff"
Referrer-Policy "strict-origin-when-cross-origin"
-Server
}
reverse_proxy vendoo:8124
}
@@ -1,60 +0,0 @@
# Vendoo 1.32.0 Abnahmebericht
**Release:** Docker, NAS & Production Deployment Foundation
**Prüfdatum:** 09.07.2026
**Ausgangsbasis:** `Vendoo_Feature_1_31_0_Multiuser_Security_Foundation.zip`
**Basis-SHA-256:** `cad2670d663c98964b7c3b4e95e5f6e475a3bcae12921339a0a84576b77d325b`
## Ergebnis
Vendoo 1.32.0 ist als vollständiges Drüberkopierpaket erstellt. Die Code-, Migrations-, Pfad-, Sicherheits- und Paketprüfungen sind bestanden. Die reale Docker-/NAS-, Windows- und Browser-End-to-End-Abnahme konnte in der bereitgestellten Linux-Sandbox nicht ausgeführt werden, weil dort weder Docker noch PowerShell/Windows noch ein Browser zur Verfügung stehen und das native `better-sqlite3`-Modul in dieser stark begrenzten Build-Umgebung nicht innerhalb des Ausführungszeitlimits kompiliert werden konnte.
Der Release ist deshalb **für Installation und reale Umgebungsabnahme vorbereitet**, aber Docker-, Windows- und Browserbetrieb werden nicht fälschlich als praktisch getestet ausgewiesen.
## Bestandene Prüfungen
| Prüfung | Status | Ergebnis/Nachweis |
|---|---|---|
| Handover-Reihenfolge | bestanden | `00_START_HIER.md` bis `14_SOURCE_PACKAGE_CHECKSUM.txt` vollständig in vorgegebener Reihenfolge gelesen |
| Basis-ZIP SHA-256 | bestanden | stimmt exakt mit Handover überein |
| Basis-Dateiprüfsummen | bestanden | 271 von 271 Dateien `OK` |
| Reale 1.31.0-Codeanalyse | bestanden | RBAC, Sessions, Audit, Locks, Setup, Windows-Menü, FLUX-Trennung und reale Deployment-Lücken geprüft |
| Versionssynchronität | bestanden | Paket, Lockfile, Manifest, UI-Build und Windows-Setup = `1.32.0` |
| JS-/MJS-Syntax | bestanden | alle geänderten Laufzeitdateien sowie Verifikator mit `node --check` |
| Shell-Syntax | bestanden | Entry-Point, Backup und Restore mit `sh -n` |
| YAML-Syntax | bestanden | `compose.yaml` und Bind-Mount-Override mit PyYAML geladen |
| Datenbankmigration frisch | bestanden | 68 additive DB-Ausführungsblöcke; Pflichttabellen vorhanden |
| Datenbankmigration bestehend | bestanden | vorhandener Testdatensatz blieb erhalten; Publishing- und Operations-Struktur gültig |
| Lockfile-Auflösung | bestanden | sauberer `npm ci --ignore-scripts`: 151 Pakete installiert |
| Laufzeitpfade | bestanden | DB, Uploads, Backups, Operations und Logs in getrenntem temporären Datenbereich beschreibbar |
| Setup-Token Entry-Point | bestanden | fehlender Token beendet Produktion mit Exit 78; 32-Zeichen-Token akzeptiert |
| Deployment-Gate | bestanden | Version, Pfadtrennung, Readiness, Shutdown, Setup-Schutz, Origins, Container-Härtung und Datenhygiene |
| Datenhygiene | bestanden | keine `.env`, DB, Logs, Uploads, Backups, Operations, Modelle oder `node_modules` im Anwendungspaket |
| Secret-Musterscan | bestanden | keine erkannten privaten Schlüssel, AWS- oder `sk-`-Live-Schlüssel |
| FLUX/VTO-Regel | bestanden | FLUX bleibt getrennt; Hauptcontainer standardmäßig deaktiviert; freier Workflow ohne `LoadImage`; kein VTO-Wiedereinbau |
| Originalbildschutz | bestanden | geänderte Pfadlogik erzeugt keine destruktive Originalüberschreibung |
## Nicht ausgeführte beziehungsweise nicht vollständig ausführbare Prüfungen
| Prüfung | Status | Grund |
|---|---|---|
| vollständiges `npm ci` mit nativen Install-Skripten | nicht abgeschlossen | Registry-/GitHub-Prebuild war nicht verfügbar; lokaler `better-sqlite3`-Fallback kompilierte in der Sandbox auch nach 5 bzw. 10 Minuten nicht fertig |
| Serverstart und API-Smoke-Test | nicht ausgeführt | natives `better-sqlite3`-Binary dadurch nicht verfügbar |
| Docker-Build | nicht ausgeführt | `docker` ist in der Sandbox nicht installiert (`exit 127`) |
| `docker compose config` über Docker CLI | nicht ausgeführt | Docker fehlt; YAML wurde statisch erfolgreich validiert |
| Container-Healthcheck/Persistenz/Backup/Restore | nicht ausgeführt | Docker fehlt; Skripte und Mount-Logik wurden statisch geprüft |
| Reverse-Proxy-/HTTPS-Livetest | nicht ausgeführt | keine Proxy-/TLS-Laufzeit vorhanden |
| Windows-Start/Update | nicht ausgeführt | kein Windows und kein PowerShell vorhanden; reale Menüpunkte 2 und 3 statisch bestätigt |
| Login, Session, Logout, Rollen, Upload, Artikel, SmartCopy, Publish-Center | nicht ausgeführt | Server-/Browserlaufzeit nicht verfügbar |
| Dark Mode, Responsive, Tastatur/Fokus | nicht ausgeführt | kein Browser-End-to-End-Test; dieser Slice verändert keine Haupt-UI-Layouts, nur das Setup-Token-Feld im Login |
| echte Plattform-APIs | nicht ausgeführt | bewusst keine Veröffentlichung ausgelöst |
## Reale Abnahme nach Installation
Der Betreiber muss die in `INSTALLATION_1_32_0_WINDOWS_DOCKER_NAS.md` beschriebene Funktionsprüfung ausführen. Besonders wichtig sind `/readyz`, Login/Logout, Rollen, bestehende Artikel und Bilder, Upload, Containerneustart, Testbackup, Restore in einem sicheren Testpfad sowie ein Reverse-Proxy-Test mit HTTPS.
## Bekannte Folgepunkte
- Widerrufbare, minimale Browser-Extension-Tokenkopplung statt dauerhafter Cookie-Abhängigkeit bleibt ein späterer Security-Slice.
- Offline-Notfallverfahren für den verlorenen letzten Administrator bleibt ein späterer Operations-Slice.
- Ein veröffentlichtes, signiertes Container-Image und automatisierte CI-Builds sind noch nicht Bestandteil dieses Pakets.
@@ -1,34 +0,0 @@
# Vendoo 1.33.0 Abnahmebericht
**Release:** Multiplatform Deployment Wizard & Flux/Admin Fixes
**Prüfdatum:** 09.07.2026
**Basis:** Vendoo 1.32.0
## Bestandene statische Prüfungen
- Versionsgleichstand in Paket, Lockfile, UI, Compose, Manifest und Windows-Setup
- JavaScript-/MJS-Syntax der geänderten Dateien
- POSIX-Shell-Syntax von `setup.sh`
- Deployment-Gate 1.33.0
- Windows-Assistent enthält alle vier Zieltypen
- Linux-Assistent enthält Docker-, NAS- und VPS-Modus
- Compose behält non-root, read-only, Healthcheck und getrennte Volumes
- FLUX-Historie wählt beim Laden kein Bild mehr automatisch aus
- Reset-Funktion löscht weder Verlauf noch Bilder noch Jobs
- Benutzeraktionen verwenden gebundene Event-Listener
- Passwortvalidierung findet vor dem Benutzer-Update statt
- Benutzer-Update liefert einen sanitiserten Datensatz
- keine produktive `.env`, DB, Uploads, Backups, Logs, Operations oder `node_modules` im Release
## Nicht als praktisch getestet ausgewiesen
- Windows PowerShell 5.1 Laufzeit, da die Sandbox kein Windows/PowerShell enthält
- Docker-Build und Containerstart, da kein Docker-Daemon vorhanden ist
- Portainer-Import und herstellerspezifische NAS-Oberflächen
- realer VPS-Reverse-Proxy und TLS
- Browser-End-to-End-Klicktest
- native Serverlaufzeit mit `better-sqlite3`
## Abnahmeentscheidung
Das Paket ist als Drüberkopier-Release und als geführte Installationsgrundlage vorbereitet. Die reale Zielsystemabnahme muss nach `02_INSTALLATION_UND_ABNAHME.md` erfolgen. Kein nicht ausgeführter Laufzeittest wird als bestanden dargestellt.
@@ -1,50 +0,0 @@
# Vendoo 1.34.0 Abnahmebericht
**Release:** GitHub CI/CD & Zero-Edit Installer Foundation
**Prüfdatum:** 09.07.2026
**Basis:** Vendoo 1.33.0
## Umgesetzte Abnahmepunkte
- geführte Windows-Installationsmaske für lokalen Betrieb und Docker Desktop,
- geführter Shell-Assistent für Linux, macOS, NAS/Portainer und VPS,
- keine manuelle Bearbeitung von `.env`, Compose oder Caddy-Konfiguration erforderlich,
- automatisch erzeugter Erst-Admin-Code,
- Eingabevalidierung für Port, URL und Domain,
- automatisches VPS-HTTPS über getrennten Caddy-Stack,
- persistenter Runtime-Konfigurationsspeicher für Einstellungen im read-only Container,
- CI für reproduzierbare Installation, Syntax, Migrationen, Git-Sicherheit, Compose und Docker-Testbuild,
- Release-Automation für ZIP, SHA-256 und GHCR-Images,
- kontrollierter Git-Erstimport mit lokalem Sicherheitsgate,
- real angelegter Branch `release/1.34.0-initial-import`,
- real angelegter Draft Pull Request #3.
## Bestandene Prüfungen
- JavaScript-/MJS-Syntaxprüfung,
- POSIX-Shell-Syntaxprüfung,
- simulierte Installationsläufe für Docker lokal, NAS-Bind-Mount und VPS/Caddy,
- dabei erkannter und behobener Standardwert-/Prompt-Fehler im Shell-Assistenten,
- YAML-Parsing aller Compose- und GitHub-Workflow-Dateien,
- Deployment-Gate 1.34.0,
- Git-Sicherheitsgate,
- Datenbankmigrationstest gegen frische und bestehende Testdatenbank,
- bestehender Testdatensatz blieb erhalten,
- persistenter Konfigurationsspeicher einschließlich Dateirechten und Mehrzeilen-Sperre,
- Versionsgleichstand von Paket, Lockfile, UI, Manifest, Compose und Installer,
- kein produktives Secret oder Laufzeitdatum im bereinigten Release.
## Nicht als praktisch getestet ausgewiesen
- tatsächlicher WinForms-/PowerShell-5.1-Lauf auf Windows,
- Docker-Build und Containerstart mit realem Docker-Daemon,
- Docker Desktop auf Windows/macOS,
- Portainer-Import auf einem realen NAS,
- Caddy-Zertifikatsausstellung mit echter Domain und öffentlichem DNS,
- Browser-End-to-End-Abnahme,
- vollständige native Node-Laufzeit mit kompiliertem `better-sqlite3`,
- veröffentlichter GitHub-Release-Workflow und GHCR-Push.
## Abnahmeentscheidung
Das Release ist als vollständiges Drüberkopier-Paket, Zero-Edit-Installationsgrundlage und kontrollierte GitHub-Importbasis freigegeben. Zielsystemtests bleiben gemäß Installations- und Abnahmeanleitung verpflichtend. Nicht ausgeführte Laufzeittests werden nicht als bestanden dargestellt.
@@ -1,20 +0,0 @@
# Vendoo 1.34.1 Abnahmebericht
## Bestanden
- JavaScript-Syntax des Git-Sicherheitsgates und des Regressionstests
- vollständiger Arbeitsbaumscan auf sauberem Release-Quellstand
- Blockierung unversionierter `.env.local`- und Token-Testdateien
- erfolgreicher Lauf nach Entfernung der Test-Secrets
- Deployment-Gate 1.34.1
- Shell-Syntax des Linux/macOS-Deploy-Assistenten
- Versionsgleichstand in Paket, Lockfile, UI, Setup und Manifest
- GitHub-Branch `release/1.34.1-initial-import` und Draft Pull Request #4 real angelegt
- Pull Request #3 geschlossen und als ersetzt dokumentiert
## Nicht als real getestet ausgewiesen
- vollständiger Lauf unter Windows PowerShell 5.1
- echte Browser-Anmeldung und kompletter Push vom Nutzer-PC
- GitHub Actions nach vollständigem Quellimport
- Docker-/NAS-/VPS-Laufzeit, da dieser Hotfix ausschließlich das Git-Sicherheitsgate betrifft
@@ -1,25 +0,0 @@
# Vendoo 1.34.2 Abnahmebericht
## Bestanden
- JavaScript-Syntax von Staging-Builder, Staging-Regressionstest, Sicherheitsgate und Deployment-Gate
- Shell-Syntax des Linux/macOS-Deploy-Assistenten
- YAML-Parsing von CI, Release und Compose-Dateien
- Git-Staging-Regressionstest: sichere Dateien kopiert, lokale `.env.local`, Operations-, Log-, Upload-, DB- und Modelltestdaten ausgeschlossen
- `.git` des temporären Klons blieb unverändert erhalten
- Git-Sicherheitsgate auf dem vollständigen Release-Quellstand
- Secret-Regressionstest mit unversionierten Testdateien
- Deployment-Gate 1.34.2
- Shell-Installer-Simulation für Docker, NAS und VPS
- Datenbankmigrationen: 68 Einheiten auf frischer und bestehender Datenbank
- vorhandener Testdatensatz blieb erhalten
- Versionsgleichstand in Paket, Lockfile, UI, Setup, Compose und Update-Manifest
## Nicht als real getestet ausgewiesen
- vollständiger Lauf unter Windows PowerShell 5.1
- echte GitHub-Browseranmeldung und kompletter Push vom Nutzer-PC
- GitHub Actions nach vollständigem Quellimport
- echter Docker-/NAS-/VPS-Lauf
Die Windows-spezifische Prozessausgabe wurde statisch geprüft; eine echte Windows-Laufzeit steht in der Erstellungsumgebung nicht zur Verfügung.
@@ -1,20 +0,0 @@
# Vendoo 1.34.3 Abnahmebericht
## Bestanden
- Staging-Regression mit `updates/backups/slice22_1_20260707-194953/scripts/install-local-flux.ps1`
- Staging-Regression mit `updates/backups/slice22_1_20260707-194953/setup.bat`
- Staging-Regression mit `updates/backups/slice22_1_20260707-194953/setup.ps1`
- aktive Root-/scripts-Installationsdateien bleiben im Staging
- Git-Sicherheitsgate auf bereinigtem Quellstand
- JavaScript-/MJS-Syntaxprüfung
- Deployment-Gate 1.34.3
- Shell-Installer-Simulation
- Datenbankmigrationsprüfung gegen frische und bestehende Testdatenbank
## Nicht als real getestet
- Windows PowerShell 5.1 auf dem Benutzerrechner
- echter Push aus dem lokalen Projektordner
- Docker-/Portainer-/VPS-Livetest
- GitHub-Actions-Lauf nach dem vollständigen Import
@@ -1,53 +0,0 @@
# Vendoo 1.35.0 Abnahmebericht
## Bestanden
- JavaScript-/MJS-Syntax aller bestehenden und neuen Kernbestandteile
- Plattform-Architecture-Gate
- zwölf Modulmanifeste und Abhängigkeiten
- Zykluserkennung
- fehlende Capability wird blockiert
- doppelte Ressourcen-Ownership wird blockiert
- Deny-by-default-Route ohne Policy wird blockiert
- nicht berechtigter Zugriff auf registrierte Route ergibt HTTP 403
- Event-Auslieferung und Owner-Cleanup
- Lifecycle- und Modulshutdown
- sichere Theme-Werte und verbotene Token
- RGB-Bereichsprüfung
- deterministische Token-Generierung
- Light, Dark und High Contrast vorhanden
- Safe-DOM-Vertrag ohne `innerHTML`
- API-Client-Vertrag mit CSRF und Same-Origin
- Deployment-Gate 1.35.0
- Git-Sicherheitsgate: 365 Dateien ohne Secrets/Laufzeitdaten
- Git-Sicherheits-Regressionstest
- Git-Staging-Regressionstest
- persistenter Konfigurationsspeicher
- Shell-Installer-Simulation für Docker, NAS und VPS
- 68 Migrationseinheiten gegen frische Datenbank
- 68 Migrationseinheiten gegen bestehende Datenbank
- vorhandener Testdatensatz blieb erhalten
## Dependency-Test
`npm ci` wurde versucht. Die Lockdatei wurde aufgelöst, aber `better-sqlite3` konnte in der Sandbox nicht fertig gebaut werden:
1. Prebuild-Download scheiterte wegen fehlender DNS-/Netzverbindung zu GitHub.
2. Der Fallback mit lokal vorhandenen Node-Headern begann erfolgreich zu kompilieren, wurde aber beim SQLite-C-Build durch das Ausführungslimit beendet.
Dieser Punkt wird nicht als bestanden ausgegeben.
## Nicht praktisch getestet
- Windows PowerShell 5.1 und WinForms
- echter Windows-Lokalstart
- echter Docker-/NAS-/Portainer-Start
- VPS/Caddy/TLS
- Browser-End-to-End-Test
- visuelle Regression aller Seiten
- vollständiger Node-Serverstart mit nativ kompiliertem `better-sqlite3`
- GitHub Actions und GHCR-Liveausführung
## Daten- und Kompatibilitätsaussage
Keine Datenbank, Uploads, Backups, Operations-Daten, Benutzer, Artikel, API-Schlüssel, FLUX-Modelle oder ComfyUI-Daten wurden in das Paket aufgenommen oder gelöscht. Es gibt keine Framework- oder Datenbankmigration.
@@ -1,32 +0,0 @@
# Abnahmebericht Vendoo 1.36.0
## Gegenstand
Secure Theme Manager, Accessibility & Component Token Foundation.
## Erfolgreich geprüft
- JavaScript-/MJS-Syntax
- Plattform-Architektur und zwölf Modulmanifeste
- natives Theme-Modul
- 42 Design Tokens und drei integrierte Themes
- Theme-Validierung und ungültige CSS-/Script-Werte
- Deny-by-default Theme-Routen
- Benutzer-/Administrator-Policy-Trennung
- Theme-Tabellen auf frischer und bestehender Datenbank
- Git-Sicherheitsgate mit 385 geprüften Dateien und Staging-Filter
- Windows-/Docker-/NAS-/VPS-Deploymentverträge
- reproduzierbare Paketauflösung mit 151 Paketen über `npm ci --ignore-scripts`
- Release-Staging mit 384 Einzeldatei-Prüfsummen
## Nicht als real ausgeführt gewertet
- Browser-End-to-End-Test unter echtem Windows
- Docker-/NAS-/VPS-Livestart
- Caddy-/TLS-Livetest
- GitHub-Actions-Livelauf
- native Kompilierung/Ausführung von `better-sqlite3` in der Sandbox; `npm ci --ignore-scripts` war erfolgreich, native Installationsskripte wurden bewusst nicht ausgeführt
## Ergebnis
Die statische, architektonische und migrationsbezogene Abnahme ist bestanden. Die genannten plattformspezifischen Laufzeittests sind nach Installation in der Zielumgebung durchzuführen.
@@ -1,3 +0,0 @@
# Abnahmebericht 1.37.0
Siehe die vollständige Release-Abnahme im Paketroot `04_ABNAHMEBERICHT.md`. Die automatisierten Gates prüfen Secret-Migration, Verschlüsselung, CSP, Request-IDs, Telemetrie, Architektur, Deployment, Installer und Datenbankkompatibilität.
@@ -1,33 +0,0 @@
# Vendoo 1.31.0 Ist- und Lückenanalyse
Stand der Prüfung: 09.07.2026
Geprüfte Basis: `Vendoo_Feature_1_31_0_Multiuser_Security_Foundation.zip`
Verifizierte SHA-256 der Basis: `cad2670d663c98964b7c3b4e95e5f6e475a3bcae12921339a0a84576b77d325b`
Die Bewertung basiert auf dem real enthaltenen Code. Paketnamen und Dokumentation wurden nicht als alleiniger Funktionsnachweis verwendet.
| Bereich | Status in 1.31.0 | Reale Fundstelle | Risiko/Lücke | Änderung in 1.32.0 |
|---|---|---|---|---|
| Versionen | bestätigt | `package.json`, Lockfile, UI-Build und Manifest = 1.31.0 | keine | auf 1.32.0 synchronisiert |
| Rollen/RBAC | bestätigt | `lib/security.mjs`, globaler `apiPermissionGuard` | einzelne Sonderrouten bleiben zusätzlich manuell zu beobachten | unverändert erhalten |
| Sessions/Login-Schutz | bestätigt, Setup-Ausnahme riskant | `lib/auth.mjs`, gehashte Tokens, Sperrlogik, Widerruf; `requireAuth` übersprang im Setup-Modus alle APIs | vor erstem Admin waren geschützte API-Routen unnötig offen; kein Offline-Notfallreset für verlorenen letzten Admin | API im Setup-Modus gesperrt; Notfallreset als Folgepunkt dokumentiert |
| CSRF/Cookies | vorhanden | Double-Submit-Cookie und Header, `HttpOnly`, dynamisches `Secure`, `SameSite=lax` | Cookie-Modus nicht konfigurierbar; Proxyannahme nur boolesch/ein Hop | Cookie-Modus konfigurierbar, Proxy-Hops/Scopes unterstützt |
| CORS/Origin | vorhanden, unvollständig | Host-/Origin-Middleware in `server.mjs` | jede Browser-Extension-Origin wurde pauschal akzeptiert | in Produktion nur konkrete Extension-Origins, unsicherer Opt-in separat |
| Audit/Locks | bestätigt | Audit-Log, `resource_locks`, Adminansicht | keine kritische Deployment-Lücke | erhalten |
| Health | teilweise | `/healthz` liefert Prozessstatus | keine Readiness-, DB- oder Schreibpfadprüfung | `/readyz` mit DB- und Volume-Schreibtest |
| Shutdown | fehlt | direkter `app.listen()` ohne Signalbehandlung | WAL/Jobs können beim Containerstopp hart beendet werden | SIGTERM/SIGINT, Server-Close, WAL-Checkpoint, DB-Close |
| Datenbankpfad | unvollständig | fest `db/vendoo.db` im Codeordner | Container-Image und Nutzerdaten nicht sauber trennbar | `VENDOO_DB_PATH` und zentrale Laufzeitpfade |
| Uploadpfad | unvollständig | fest `uploads/` im Codeordner | keine getrennte Persistenz; öffentlich statisch erreichbar | konfigurierbarer Pfad, Zugriff hinter Anmeldung |
| Uploadprüfung | Sicherheitsrisiko | Dateiendung **oder** `image/*` genügte | manipulierbarer MIME-Typ konnte beliebige Endungen umgehen | Endung **und** Bild-MIME erforderlich; Größenlimit bleibt aktiv |
| Backups | bestätigt, aber codegebunden | verifizierte ZIPs mit DB/Uploads in `operations-center.mjs` | Pfade fest an Projektroot; Live-Volume-Kopie nicht dokumentiert | separate Backup-/Operations-Volumes und sichere Stop/Backup/Start-Anleitung |
| Restore/Update | vorhanden, gestuft | Operations Center und `setup.ps1` | Container darf Anwendungscode nicht in-place überschreiben | Docker-Update nur über neues Image; Windows-Update bleibt erhalten |
| Docker/Compose | fehlt | keine entsprechenden Dateien | kein reproduzierbarer NAS-/Produktionsbetrieb | Dockerfile, Compose, Healthcheck, non-root, read-only, Volumes |
| Reverse Proxy | teilweise | Host/Origin, `PUBLIC_BASE_URL`, `trust proxy` | kein fertiger Produktionsleitfaden | HTTPS-/Proxy-Dokumentation und sichere Standardbindung |
| FLUX/ComfyUI | getrennt im Konzept | externer URL-Endpunkt; lokaler Windows-Installer | Bootstrap schreibt in Projektordner und passt nicht zu read-only Container | Container startet standardmäßig ohne FLUX; externer Dienst bleibt optional |
| Browser-Erweiterungen | real vorhanden | Chrome/Edge/Firefox/Safari-Strukturen und Pakete | Remote-Kopplung nutzt weiterhin Login-Cookie statt widerrufbarem Extension-Token | CORS gehärtet; Tokenkopplung bleibt geplanter 1.34.0-Slice |
| UI-Begriffe/Kernbereiche | weitgehend bestätigt | Navigation, Artikel, Galerie, SmartCopy, Publish und Erweiterungen im realen HTML/JS | vollständige Browser-End-to-End-Abnahme nicht statisch beweisbar | keine unnötige UI-Neuentwicklung in diesem Deployment-Slice |
| VTO | entfernt | kein aktiver FASHN-/VTO-Dienst; freier FLUX-Workflow ohne `LoadImage` | historische Dokumente enthalten weiterhin Kontext | keine VTO-Rückkehr |
## Ergebnis
1.31.0 besitzt eine echte Mehrbenutzer- und Sicherheitsgrundlage, war aber noch kein sauber containerisierbarer Produktionsstand. Die Hauptlücken lagen in der festen Kopplung von Code und Nutzerdaten, fehlender Readiness, fehlendem geordneten Shutdown, fehlenden Containerdateien sowie zu breiten Extension-Origin- und Uploadregeln.
@@ -1,23 +0,0 @@
# Vendoo Branding
Die Anwendung verwendet ab Version 1.6.2 ein gemeinsames Vendoo-Branding für Web-App, Login, mobilen Foto-Upload und Browser-Erweiterungen.
## Web-App
Assets liegen unter `public/brand/`:
- `logo/` horizontales Logo, transparente und zugeschnittene Varianten
- `icons/` App- und Mobilgrößen von 16 bis 512 Pixel
- `favicons/` ICO, PNG-Favicons, Apple Touch Icon, Android-Icons und Webmanifest
## Browser-Erweiterungen
Chrome, Edge und Firefox verwenden dieselbe Icon-Familie in 16, 32, 48 und 128 Pixeln. Popup, Browser-Toolbar, Vinted Assistant und minimierter Assistant verwenden das neue Markenzeichen.
## Farben
- Vendoo Orange: `#E63B17`
- Graphit: `#22201D`
- Warmes Off-White: `#FAF6F2`
Die Proportionen und Farben der bereitgestellten Assets sollen nicht manuell verändert werden.
@@ -1,29 +0,0 @@
# Vendoo Full Listing Editor 2026
## Ziel
Bereits gespeicherte Artikel werden nicht mehr in einem reduzierten Detailformular, sondern in einem vollständigen Arbeitsbereich bearbeitet. Generator und Listing-Editor verwenden dieselbe Rich-Text- und HTML-Logik.
## Funktionsumfang
- vollständige Bearbeitung aller Listing-Felder
- Plattform, AI-Provider, Sprache, Status, SKU und Lagerort
- Titel, Tags, Verkäufernotizen und sämtliche erkannten Attribute
- Preis und Kategorie
- Foto hinzufügen, entfernen, sortieren und als Cover festlegen
- vorhandene Fotos mit Helligkeit, Kontrast, Sättigung, Rotation, Spiegelung und Crop bearbeiten
- WYSIWYG und HTML-Code gleichzeitig sichtbar
- Änderungen im WYSIWYG erscheinen sofort im HTML-Code
- Änderungen im HTML-Code werden in den WYSIWYG-Editor zurückgeführt
- separate sandboxed Plattformvorschau
- Editor-HTML und Plattform-HTML separat kopierbar
## Datenmodell
`listings.description_html` speichert das bereinigte Rich-Text-HTML. `listings.description` bleibt als Klartext-Fallback und für Plattformen beziehungsweise Exporte erhalten.
Die neue Spalte wird über das bestehende `MIGRATIONS`-Array in `lib/db.mjs` ergänzt.
## Sicherheit
HTML wird auf unterstützte Formatierungs-Tags reduziert. Skripte, eingebettete Frames, Formulare, Event-Handler und gefährliche URLs werden entfernt. Vorschauen werden in einem `sandbox`-iframe dargestellt.
@@ -1,61 +0,0 @@
# Vendoo Listing Studio 2026
## Ziel
Der Listing-Generator ist kein Formularstapel mehr, sondern ein zusammenhängender Studio-Arbeitsplatz mit drei klaren Zonen:
1. Fotos & Medien
2. AI-Konfiguration
3. Vorschau & Bearbeitung
Die bestehende Vanilla-JS-, Express- und SQLite-Architektur bleibt erhalten.
## Fotos & Medien
- großes Cover mit vollständiger Bilddarstellung über `object-fit: contain`
- Klick auf ein Vorschaubild setzt es als Cover
- Drag & Drop sortiert die Bildreihenfolge
- maximal zehn Bilder pro Listing
- sichtbarer Foto-Check mit Qualitätsindikatoren
- bestehender Bildeditor, Hintergrundentfernung und Wasserzeichen bleiben integriert
## AI-Konfiguration
- Plattform, Provider und Modell
- Sprache und Anzahl der Varianten
- Vorlagenauswahl
- Verkäufernotizen mit Zeichenzähler
- Vorlagen übernehmen Plattform, Sprache, Hinweise und Standard-Tags
- global hinterlegte Verkäuferhinweise, Vorlagenhinweise und Artikelhinweise werden kontrolliert zusammengeführt
## Vorschau & Bearbeitung
- permanenter, kontextbezogener Ergebnisbereich
- Live-Zähler für Titel, Beschreibung und Tags
- editierbare erkannte Attribute
- Kategorie-Picker, Preis und Lagerort
- dynamische Gebührenvorschau
- nachvollziehbarer Qualitätswert
- HTML- und Plattformvorschau als optional aufklappbarer Bereich
- Speichern und Kopieren ohne Fensterwechsel
## API-Erweiterung
`POST /api/generate` akzeptiert zusätzlich:
```json
{
"template_id": 1,
"seller_notes": "Artikelspezifische Hinweise"
}
```
Standard-Tags der gewählten Vorlage werden dedupliziert mit den AI-Tags zusammengeführt.
## Qualitätsregeln
- keine neuen Frameworks
- keine neuen Datenbankspalten
- bestehende IDs und Generatorfunktionen bleiben kompatibel
- alle Farben und Zustände nutzen die Vendoo-CSS-Variablen
- Dark Mode und responsive Darstellung sind Bestandteil des Slices
@@ -1,76 +0,0 @@
# Vendoo 1.34.0 GitHub Deployment
## Repository
- Repository: `Masterluke77/vendoo`
- Sichtbarkeit: privat
- Stabiler Branch: `main`
- Entwicklungsbranch: `develop`
- Erstimport-Branch: `release/1.34.0-initial-import`
## Kontrollierter Erstimport
Unter Windows wird `GitHub-Deploy-Assistent.bat` gestartet. Der Assistent:
1. prüft beziehungsweise installiert Git für Windows über `winget`,
2. klont die vorhandene GitHub-Baseline in einen temporären Arbeitsordner,
3. verwendet oder erstellt `release/1.34.0-initial-import`,
4. kopiert nur den bereinigten Vendoo-Quellstand,
5. blockiert `.env`, Datenbanken, Uploads, Backups, Logs, Laufzeitdaten und Modelle,
6. führt nach Möglichkeit `tools/verify-git-safety.mjs` aus,
7. zeigt alle Änderungen vor dem Commit,
8. verlangt zur Freigabe die exakte Eingabe `PUSH`,
9. pusht ausschließlich den Release-Branch,
10. öffnet den vorbereiteten Pull-Request-Vergleich im Browser.
Der Assistent löscht oder verändert keine produktiven Vendoo-Daten. Der temporäre Git-Arbeitsordner wird nach Abschluss entfernt.
## Pull Request und Merge
Der Pull Request wird gegen `main` erstellt. Vor dem Merge müssen die GitHub-Actions-Prüfungen erfolgreich sein:
- reproduzierbare Installation über `npm ci`,
- Git-Sicherheitsgate,
- JavaScript-/MJS-Syntax,
- Deployment-Gate 1.34.0,
- Datenbankmigrationstest,
- Compose-Prüfung für lokal, NAS und VPS,
- Docker-Testbuild.
Empfohlen ist ein Squash-Merge. Erst danach wird ein GitHub Release `v1.34.0` veröffentlicht.
## Release-Automation
Beim Veröffentlichen eines GitHub Releases:
- wird ein bereinigtes Release-Staging erzeugt,
- werden Einzeldatei-SHA-256-Prüfsummen erzeugt,
- wird `Vendoo_1.34.0.zip` gebaut,
- wird eine SHA-256-Datei für das ZIP erzeugt,
- werden beide Dateien an das GitHub Release angehängt,
- wird ein Multi-Arch-Container für `linux/amd64` und `linux/arm64` gebaut,
- wird das Image als `ghcr.io/masterluke77/vendoo` in die GitHub Container Registry veröffentlicht,
- wird der veröffentlichte Image-Digest mit einer GitHub-Provenienz-Attestierung versehen.
Das Release-ZIP wird nicht dauerhaft in die Git-Historie committed.
## Secrets
Produktive Secrets gehören ausschließlich in:
- die lokale `.env`, die der Installer automatisch erzeugt,
- den persistenten Runtime-Konfigurationsspeicher von Vendoo,
- gegebenenfalls geschützte GitHub Environments für spätere Deployments.
Nicht zulässig sind Secrets in Quellcode, Issues, Pull Requests, Workflow-Ausgaben oder Release-Paketen.
## Späteres Produktionsdeployment
Ein automatisches Deployment auf NAS oder VPS wird erst freigeschaltet, wenn diese Gates praktisch bestätigt sind:
- Backup und Restore auf dem Zielsystem,
- Readiness nach Update,
- Rollback auf die vorherige Container-Version,
- TLS und Domainprüfung,
- getrennte Staging- und Produktionsumgebung,
- manuelle Freigabe des GitHub Environments `production`.

Some files were not shown because too many files have changed in this diff Show More