Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94d898e445 | ||
|
|
0a3d0b86e5 | ||
|
|
20f2e9a299 | ||
|
|
637275effc | ||
|
|
40071f718e | ||
|
|
6f48827f4d |
@@ -0,0 +1,6 @@
|
||||
root = true
|
||||
|
||||
[*.{bat,cmd}]
|
||||
charset = latin1
|
||||
end_of_line = crlf
|
||||
insert_final_newline = true
|
||||
@@ -87,3 +87,23 @@ VENDOO_CONFIG_PATH=
|
||||
# VENDOO_MASTER_KEY=
|
||||
VENDOO_JSON_LOGS=true
|
||||
SMTP_TLS_REJECT_UNAUTHORIZED=true
|
||||
# Coolify / GitHub production deployment
|
||||
VENDOO_INITIAL_DISABLED_MODULES=vendoo.flux-studio
|
||||
VENDOO_DEPLOY_PROVIDER=none
|
||||
COOLIFY_API_URL=
|
||||
COOLIFY_RESOURCE_UUID=
|
||||
COOLIFY_TRIGGER_MODE=webhook
|
||||
COOLIFY_DEPLOY_METHOD=GET
|
||||
COOLIFY_DEPLOY_ENDPOINT=/api/v1/deploy?uuid={uuid}&force={force}
|
||||
COOLIFY_DEPLOYMENT_STATUS_ENDPOINT=/api/v1/deployments/{deployment_id}
|
||||
VENDOO_DEPLOY_TIMEOUT_SECONDS=900
|
||||
VENDOO_DEPLOY_HEALTH_POLL_SECONDS=15
|
||||
VENDOO_BUILD_REVISION=
|
||||
VENDOO_COOLIFY_AUTO_DEPLOY=false
|
||||
VENDOO_GITHUB_REPOSITORY=Masterluke77/vendoo
|
||||
VENDOO_GITHUB_BRANCH=main
|
||||
VENDOO_GHCR_IMAGE=ghcr.io/masterluke77/vendoo
|
||||
VENDOO_UPDATE_CHANNEL=stable
|
||||
VENDOO_BACKUP_BEFORE_DEPLOY=true
|
||||
VENDOO_DEPLOY_BACKUP_UPLOADS=false
|
||||
# COOLIFY_API_TOKEN and COOLIFY_DEPLOY_WEBHOOK_URL belong in the encrypted secret store.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
* text=auto eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.cmd text eol=crlf
|
||||
@@ -5,6 +5,7 @@ on:
|
||||
branches: [main, develop, 'feature/**', 'release/**', 'hotfix/**']
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -42,9 +43,39 @@ jobs:
|
||||
- name: Git-Staging-Filter Regressionstest
|
||||
run: npm run verify:git-staging
|
||||
|
||||
- name: Release-Manifest und Paketvertrag prüfen
|
||||
run: npm run verify:release-manifest
|
||||
|
||||
- name: Git-Ignore-Grenzen für Quell- und Runtimeordner prüfen
|
||||
run: npm run verify:ignore-boundaries
|
||||
|
||||
- name: Syntaxprüfung
|
||||
run: npm run check
|
||||
|
||||
- name: PowerShell-Regressionen statisch prüfen
|
||||
run: npm run verify:powershell-static
|
||||
|
||||
- name: Updater-3.4-Lifecycle und Startkette prüfen
|
||||
run: npm run verify:updater-start-chain && npm run verify:updater-lifecycle
|
||||
|
||||
- name: Produktiven Source-Root und Archivgrenzen prüfen
|
||||
run: npm run verify:source-boundaries
|
||||
|
||||
- name: ESM-Exportverträge prüfen
|
||||
run: npm run verify:esm-exports
|
||||
|
||||
- name: FLUX-Loop-Hotfix prüfen
|
||||
run: npm run verify:flux-loop
|
||||
|
||||
- name: Vollständigen Modul-Capability-Graph prüfen
|
||||
run: npm run verify:capabilities
|
||||
|
||||
- name: Coolify-Deployment und Web-Updates prüfen
|
||||
run: npm run verify:coolify
|
||||
|
||||
- name: Initial deaktivierte Module prüfen
|
||||
run: npm run verify:initial-modules
|
||||
|
||||
- name: Plattformarchitektur und Design Tokens prüfen
|
||||
run: npm run verify:architecture
|
||||
|
||||
@@ -54,6 +85,15 @@ jobs:
|
||||
- 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: Artikel, Lager und Medien prüfen
|
||||
run: npm run verify:catalog
|
||||
|
||||
- name: Modulmanager, Pakete und Aktivierungsgrenzen prüfen
|
||||
run: npm run verify:modules
|
||||
|
||||
- name: Deployment-Gate
|
||||
run: npm run verify:deployment
|
||||
|
||||
@@ -84,3 +124,115 @@ jobs:
|
||||
|
||||
- name: Docker-Image testweise bauen
|
||||
run: docker build --pull --tag vendoo:ci .
|
||||
|
||||
windows-release-contract:
|
||||
name: Windows – vollständiger Releasevertrag
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 35
|
||||
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: Alle PowerShell-Dateien mit Windows PowerShell 5.1 parsen
|
||||
shell: powershell
|
||||
run: .\tools\verify-powershell-parser.ps1 -ReportPath "$env:RUNNER_TEMP\powershell-parser-diagnostics.txt"
|
||||
|
||||
- name: Parserdiagnose bei Fehler sichern
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: powershell-parser-diagnostics-${{ github.event.pull_request.head.sha || github.sha }}
|
||||
path: ${{ runner.temp }}/powershell-parser-diagnostics.txt
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
|
||||
- name: Vollständigen Vendoo-Releasevertrag unter Windows ausführen
|
||||
shell: pwsh
|
||||
run: npm run verify:all
|
||||
|
||||
package-after-acceptance:
|
||||
name: Updater-3.4-Paket nach Abnahme
|
||||
needs: [quality, windows-release-contract]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Exakten geprüften Head auschecken
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
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: main für den Provenienzvergleich aktualisieren
|
||||
run: git fetch origin main:refs/remotes/origin/main
|
||||
|
||||
- name: Reproduzierbares Root-Manifest bestätigen
|
||||
shell: bash
|
||||
run: |
|
||||
node tools/generate-release-manifest.mjs .
|
||||
git diff --exit-code -- release-manifest.json
|
||||
|
||||
- name: Paket mit unveränderlicher Provenienz erzeugen
|
||||
env:
|
||||
VENDOO_SOURCE_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
run: node tools/build-release.mjs
|
||||
|
||||
- name: Paketmanifest und SHA-256 prüfen
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
release_name="$(tr -d '\r\n' < release-output/RELEASE_NAME.txt)"
|
||||
package_dir="release-output/${release_name}"
|
||||
node --input-type=module - "$package_dir" <<'NODE'
|
||||
import { readAndValidateManifest } from './tools/release-manifest-lib.mjs';
|
||||
const packageDir = process.argv[2];
|
||||
const manifest = readAndValidateManifest(packageDir);
|
||||
if (manifest.schema !== 'vendoo-release-package-v2') throw new Error(`Unerwartetes Paketschema: ${manifest.schema}`);
|
||||
if (manifest.updaterVersion !== '3.4.0') throw new Error(`Unerwartete Updater-Version: ${manifest.updaterVersion}`);
|
||||
if (manifest.targetVersion !== '1.43.0') throw new Error(`Unerwartete Zielversion: ${manifest.targetVersion}`);
|
||||
console.log(`Paket validiert: ${manifest.targetVersion}, Updater ${manifest.updaterVersion}, Payload ${manifest.payloadHash}`);
|
||||
NODE
|
||||
archive="release-output/${release_name}.zip"
|
||||
python tools/build-deterministic-zip.py "$package_dir" "$archive"
|
||||
first_hash="$(sha256sum "$archive" | awk '{print $1}')"
|
||||
python tools/build-deterministic-zip.py "$package_dir" "$archive"
|
||||
second_hash="$(sha256sum "$archive" | awk '{print $1}')"
|
||||
if [[ "$first_hash" != "$second_hash" ]]; then
|
||||
echo "Der ZIP-Build ist nicht byte-reproduzierbar." >&2
|
||||
exit 1
|
||||
fi
|
||||
python -m zipfile -t "$archive"
|
||||
(
|
||||
cd release-output
|
||||
sha256sum "${release_name}.zip" > "${release_name}.zip.sha256"
|
||||
sha256sum --check "${release_name}.zip.sha256"
|
||||
)
|
||||
|
||||
- name: Abgenommenes Paket als CI-Artefakt bereitstellen
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: vendoo-1.43.0-updater-3.4-${{ github.event.pull_request.head.sha || github.sha }}
|
||||
path: |
|
||||
release-output/*.zip
|
||||
release-output/*.zip.sha256
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
|
||||
@@ -16,7 +16,20 @@ env:
|
||||
IMAGE_NAME: masterluke77/vendoo
|
||||
|
||||
jobs:
|
||||
powershell-parser:
|
||||
name: Windows PowerShell 5.1 Parser
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Repository auschecken
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Alle PowerShell-Dateien mit Windows PowerShell 5.1 parsen
|
||||
shell: powershell
|
||||
run: .\tools\verify-powershell-parser.ps1
|
||||
|
||||
release-assets:
|
||||
needs: powershell-parser
|
||||
name: Release-Paket und Prüfsummen
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -42,21 +55,21 @@ jobs:
|
||||
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: ESM-Exportverträge explizit prüfen
|
||||
run: npm run verify:esm-exports
|
||||
|
||||
- name: Release-Staging erzeugen
|
||||
- name: FLUX-Loop-Hotfix explizit prüfen
|
||||
run: npm run verify:flux-loop
|
||||
|
||||
- name: Vollständige Prüfung
|
||||
run: npm run verify:all
|
||||
|
||||
- name: Release-Manifest reproduzierbar prüfen
|
||||
run: |
|
||||
node tools/generate-release-manifest.mjs .
|
||||
git diff --exit-code -- release-manifest.json
|
||||
|
||||
- name: Manifestbasiertes Release-Staging erzeugen
|
||||
run: node tools/build-release.mjs
|
||||
|
||||
- name: ZIP und SHA-256 erzeugen
|
||||
@@ -121,6 +134,7 @@ jobs:
|
||||
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=stable,enable=${{ !github.event.release.prerelease }}
|
||||
type=raw,value=latest,enable=${{ !github.event.release.prerelease }}
|
||||
|
||||
- name: Container bauen und veröffentlichen
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
name: Vendoo Release Manifest Sync
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'release/*-production-update-v*'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
actions: write
|
||||
|
||||
concurrency:
|
||||
group: vendoo-release-manifest-sync-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
name: Release-Manifest reproduzierbar synchronisieren
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Release-Branch auschecken
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Node.js 22 aktivieren
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.x'
|
||||
|
||||
- name: Release-Manifest erzeugen
|
||||
run: node tools/generate-release-manifest.mjs .
|
||||
|
||||
- name: Geändertes Manifest committen
|
||||
id: manifest
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if git diff --quiet -- release-manifest.json; then
|
||||
echo "Release-Manifest ist bereits aktuell."
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
echo "head_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
git config user.name "vendoo-release-bot"
|
||||
git config user.email "vendoo-release-bot@users.noreply.github.com"
|
||||
git add release-manifest.json
|
||||
git commit -m "chore: Release-Manifest synchronisieren [manifest-sync]"
|
||||
git push origin HEAD:${GITHUB_REF_NAME}
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
echo "head_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Finalen Manifest-Head explizit validieren
|
||||
if: ${{ steps.manifest.outputs.changed == 'true' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
final_head="${{ steps.manifest.outputs.head_sha }}"
|
||||
remote_head="$(git ls-remote origin "refs/heads/${GITHUB_REF_NAME}" | awk '{print $1}')"
|
||||
if [[ -z "$remote_head" || "$remote_head" != "$final_head" ]]; then
|
||||
echo "Der gepushte Manifest-Head ist nicht stabil: lokal=$final_head remote=$remote_head" >&2
|
||||
exit 1
|
||||
fi
|
||||
gh workflow run ci.yml --repo "$GITHUB_REPOSITORY" --ref "$GITHUB_REF_NAME"
|
||||
gh workflow run sync-release-manifest.yml --repo "$GITHUB_REPOSITORY" --ref "$GITHUB_REF_NAME"
|
||||
echo "Vendoo CI und Manifest-Sync wurden für finalen Head $final_head explizit registriert."
|
||||
@@ -0,0 +1,83 @@
|
||||
name: Vendoo Production Deploy
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
target_version:
|
||||
description: Expected Vendoo version
|
||||
required: true
|
||||
type: string
|
||||
public_base_url:
|
||||
description: Public Vendoo URL
|
||||
required: true
|
||||
default: https://vendoo.flatlined.de
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: vendoo-production-deploy
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Validate inputs
|
||||
shell: bash
|
||||
env:
|
||||
TARGET_VERSION: ${{ inputs.target_version }}
|
||||
PUBLIC_BASE_URL: ${{ inputs.public_base_url }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
[[ "$TARGET_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]
|
||||
[[ "$PUBLIC_BASE_URL" =~ ^https://[^/]+/?$ ]]
|
||||
|
||||
- name: Trigger Coolify
|
||||
shell: bash
|
||||
env:
|
||||
COOLIFY_DEPLOY_WEBHOOK_URL: ${{ secrets.COOLIFY_DEPLOY_WEBHOOK_URL }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
test -n "$COOLIFY_DEPLOY_WEBHOOK_URL"
|
||||
curl --fail --silent --show-error --location --request GET \
|
||||
--connect-timeout 20 --max-time 90 \
|
||||
"$COOLIFY_DEPLOY_WEBHOOK_URL" >/tmp/coolify-response.txt
|
||||
echo "Coolify accepted the deployment trigger."
|
||||
|
||||
- name: Wait for exact production version
|
||||
shell: bash
|
||||
env:
|
||||
TARGET_VERSION: ${{ inputs.target_version }}
|
||||
PUBLIC_BASE_URL: ${{ inputs.public_base_url }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
BASE_URL="${PUBLIC_BASE_URL%/}"
|
||||
deadline=$((SECONDS + 1500))
|
||||
last_version="unknown"
|
||||
while (( SECONDS < deadline )); do
|
||||
if body=$(curl --fail --silent --show-error --connect-timeout 10 --max-time 30 \
|
||||
-H 'Accept: application/json' -H 'Cache-Control: no-cache' \
|
||||
"$BASE_URL/readyz?github_run=${GITHUB_RUN_ID}&attempt=${GITHUB_RUN_ATTEMPT}"); then
|
||||
ready=$(jq -r '.ok // false' <<<"$body")
|
||||
version=$(jq -r '.version // empty' <<<"$body")
|
||||
if [[ -n "$version" ]]; then last_version="$version"; fi
|
||||
echo "ready=$ready version=${version:-unknown} expected=$TARGET_VERSION"
|
||||
if [[ "$ready" == "true" && "$version" == "$TARGET_VERSION" ]]; then exit 0; fi
|
||||
fi
|
||||
sleep 15
|
||||
done
|
||||
echo "Timeout waiting for Vendoo $TARGET_VERSION. Last version: $last_version" >&2
|
||||
exit 1
|
||||
|
||||
- name: Final health response
|
||||
shell: bash
|
||||
env:
|
||||
PUBLIC_BASE_URL: ${{ inputs.public_base_url }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
BASE_URL="${PUBLIC_BASE_URL%/}"
|
||||
curl --fail --silent --show-error -H 'Accept: application/json' \
|
||||
"$BASE_URL/healthz?github_run=${GITHUB_RUN_ID}" | jq .
|
||||
@@ -0,0 +1,125 @@
|
||||
name: Vendoo Windows Release Diagnostics
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: vendoo-windows-diagnostics-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
windows-release-diagnostics:
|
||||
name: Windows – Release-Gates einzeln
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 35
|
||||
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: Alle PowerShell-Dateien mit Windows PowerShell 5.1 parsen
|
||||
shell: powershell
|
||||
run: .\tools\verify-powershell-parser.ps1
|
||||
|
||||
- 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: Release-Manifest prüfen
|
||||
run: npm run verify:release-manifest
|
||||
|
||||
- name: Git-Ignore-Grenzen prüfen
|
||||
run: npm run verify:ignore-boundaries
|
||||
|
||||
- name: Syntax und Identity-Datenbank prüfen
|
||||
run: npm run check
|
||||
|
||||
- name: PowerShell-Regressionen statisch prüfen
|
||||
run: npm run verify:powershell-static
|
||||
|
||||
- name: Source-Root-Grenzen prüfen
|
||||
run: npm run verify:source-boundaries
|
||||
|
||||
- name: ESM-Exportverträge prüfen
|
||||
run: npm run verify:esm-exports
|
||||
|
||||
- name: FLUX-Loop-Hotfix prüfen
|
||||
run: npm run verify:flux-loop
|
||||
|
||||
- name: Capability-Graph prüfen
|
||||
run: npm run verify:capabilities
|
||||
|
||||
- name: Coolify- und Produktionsoperationen prüfen
|
||||
run: npm run verify:coolify
|
||||
|
||||
- name: Initial deaktivierte Module prüfen
|
||||
run: npm run verify:initial-modules
|
||||
|
||||
- name: Plattformarchitektur prüfen
|
||||
run: npm run verify:architecture
|
||||
|
||||
- name: Theme Manager prüfen
|
||||
run: npm run verify:themes
|
||||
|
||||
- name: Security Foundation prüfen
|
||||
run: npm run verify:security
|
||||
|
||||
- name: Identity und Settings prüfen
|
||||
run: npm run verify:identity
|
||||
|
||||
- name: Einladungen prüfen
|
||||
run: npm run verify:invitations
|
||||
|
||||
- name: SQLite-Cleanup unter Windows prüfen
|
||||
run: npm run verify:sqlite-cleanup
|
||||
|
||||
- name: Katalog und Medien prüfen
|
||||
run: npm run verify:catalog
|
||||
|
||||
- name: Modulmanager prüfen
|
||||
run: npm run verify:modules
|
||||
|
||||
- name: Produktionsoperationen prüfen
|
||||
run: npm run verify:production-operations
|
||||
|
||||
- name: One-Click-Updater prüfen
|
||||
run: npm run verify:one-click-update
|
||||
|
||||
- name: Modulnavigation prüfen
|
||||
run: npm run verify:module-navigation
|
||||
|
||||
- name: Updater-UI prüfen
|
||||
run: npm run verify:updater-ui
|
||||
|
||||
- name: Updater-Hotfix-Vertrag prüfen
|
||||
run: npm run verify:updater-hotfix
|
||||
|
||||
- name: Deployment prüfen
|
||||
run: npm run verify:deployment
|
||||
|
||||
- name: Konfigurationsspeicher prüfen
|
||||
run: npm run verify:config
|
||||
|
||||
- name: Installer-Shell-Portabilität prüfen
|
||||
run: npm run verify:installer-shell
|
||||
|
||||
- name: Datenbankmigrationen prüfen
|
||||
run: npm run verify:db
|
||||
@@ -13,22 +13,22 @@
|
||||
node_modules/
|
||||
|
||||
# SQLite runtime data
|
||||
db/*.db
|
||||
db/*.db-shm
|
||||
db/*.db-wal
|
||||
db/*.sqlite
|
||||
db/*.sqlite3
|
||||
/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/
|
||||
/uploads/*
|
||||
!/uploads/.gitkeep
|
||||
/backups/
|
||||
/logs/
|
||||
/tmp/
|
||||
/temp/
|
||||
/sessions/
|
||||
/data/
|
||||
/docker-data/
|
||||
*.log
|
||||
|
||||
# OS and editor files
|
||||
@@ -43,42 +43,54 @@ 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-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/
|
||||
|
||||
# Historical handover and feature-package archives (never source)
|
||||
/Archiv/
|
||||
/archive/
|
||||
/archives/
|
||||
|
||||
# Local update, rollback and slice archives
|
||||
updates/
|
||||
/updates/
|
||||
|
||||
# Operations Center runtime
|
||||
operations/staging/
|
||||
operations/updates/
|
||||
operations/rollback/
|
||||
operations/apply-*/
|
||||
operations/pending-operation.json
|
||||
operations/last-operation.json
|
||||
/operations/staging/
|
||||
/operations/updates/
|
||||
/operations/rollback/
|
||||
/operations/apply-*/
|
||||
/operations/pending-operation.json
|
||||
/operations/last-operation.json
|
||||
|
||||
# Deployment assistant state
|
||||
.vendoo-install-mode
|
||||
runtime/
|
||||
/.vendoo-install-mode
|
||||
/runtime/
|
||||
# Generated deployment and release output
|
||||
release-output/
|
||||
/release-output/
|
||||
*.release.zip
|
||||
*.release.sha256.txt
|
||||
.vendoo-github-state.json
|
||||
/.vendoo-github-state.json
|
||||
|
||||
# First-run and local installer state
|
||||
operations/first-admin-code.txt
|
||||
config/local/
|
||||
/operations/first-admin-code.txt
|
||||
/config/local/
|
||||
|
||||
|
||||
# Installed Vendoo module packages (runtime)
|
||||
/modules/
|
||||
|
||||
# Python cache
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# Vendoo 1.43.0 – Start hier
|
||||
|
||||
## Production Updater 3.3 starten
|
||||
|
||||
1. Dieses ZIP vollständig in einen neuen lokalen Ordner entpacken, zum Beispiel `C:\Vendoo-Update`.
|
||||
2. Im Ordner `vendoo` doppelt auf `UPDATE_VENDOO.bat` klicken.
|
||||
3. Den Vendoo Production Updater bis zum eindeutigen Ergebnis geöffnet lassen.
|
||||
|
||||
Der Updater zeigt zehn klare Phasen, Fortschritt, Live-Protokoll und einen dauerhaft sichtbaren Fehlerzustand. Beim ersten Lauf kann einmalig die GitHub-Anmeldung im Browser erforderlich sein. GitHub CLI wird bei Bedarf als verwaltete portable Kopie geladen und per SHA-256 geprüft.
|
||||
|
||||
Ein Coolify-Webhook wird nicht abgefragt. Nach einem erfolgreichen Merge verwendet Vendoo das bereits eingerichtete Coolify Auto Deploy der GitHub-Verknüpfung und bestätigt anschließend `/readyz` mit exakt Version `1.43.0`.
|
||||
|
||||
## Release-Architektur 3.0
|
||||
|
||||
- Die geklonte `main`-Arbeitskopie wird nicht geleert.
|
||||
- `release-manifest.json` enthält jede auszuliefernde Datei mit Größe und SHA-256.
|
||||
- Pflichtdateien wie `db/schema.sql` werden vor den Tests hart geprüft.
|
||||
- Dateien werden als Overlay angewendet und im Ziel erneut gehasht.
|
||||
- `release-manifest.json` wird anschließend als bytegeprüfte Steuerdatei in die Arbeitskopie übernommen.
|
||||
- Löschungen sind nur über die explizite Liste `removedFiles` erlaubt.
|
||||
- Alte Updater-2.x-Sitzungen werden nicht übernommen.
|
||||
- GitHub Actions führt den vollständigen Releasevertrag auf Windows und Linux aus.
|
||||
|
||||
## Inhalt von Vendoo 1.43.0
|
||||
|
||||
- modulabhängige Navigation: deaktivierte Module verschwinden sofort aus der Seitenleiste,
|
||||
- optionales, standardmäßig deaktiviertes Modul **Produktbild Studio**,
|
||||
- grundlegend überarbeitete Seite **Neuer Artikel**,
|
||||
- dauerhaft sichtbare Aktionen **Artikel generieren** und **Speichern**,
|
||||
- manifestbasierter Production Updater 3.3.
|
||||
|
||||
## Sicherheitsgrenzen
|
||||
|
||||
Der Updater ersetzt oder löscht niemals `/app/data`, Datenbanken, Uploads, Backups, `.env` oder API-Schlüssel. GitHub-Checks, kontrollierter Merge, Coolify Auto Deploy und `/readyz`-Versionskontrolle bleiben verpflichtend.
|
||||
|
||||
Technische Details: `docs/PRODUCTION_UPDATER_3_3.md`.
|
||||
@@ -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 A–E, 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,5–5 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, 1–3 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
|
||||
- 2–3 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%
|
||||
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
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 1–3 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`.
|
||||