Files
refboard-ayon/README.md
T

9.3 KiB
Raw Blame History

RefBoard AYON

Kollaborative Referenz-Bildwand (PureRef-on-the-web), umgebaut für den AYON-only-Betrieb. Fork von metalfinger/refboard (vollständige History erhalten).

Das Besondere: Es gibt keinen RefBoard-Login mehr. Nutzer öffnen Boards aus dem AYON-Launcher heraus und sind automatisch mit ihrer AYON-Identität eingeloggt. Boards gehören zu AYON-Tasks (<Projekt>/<Task-Pfad>), nicht zu Personen. Alle Kollegen mit Projektzugriff arbeiten kollaborativ am selben Board (Echtzeit, Socket.IO).

Architektur

Launcher (Task ausgewählt)
  → "RefBoard öffnen" (Server-Addon-Action)
  → POST /api/addons/refboard/<ver>/session   (AYON-Auth via Bearer)
      → Addon prüft Projektzugriff, legt Single-Use-Ticket an (60 s TTL)
  ← { url: "https://<refboard>/b?ticket=…&project=…&task=…" }
  → Launcher öffnet Browser auf dieser URL
      → RefBoard-Frontend (Route /b) ruft POST /api/auth/ayon/exchange
      → RefBoard-Backend ⇄ Addon /exchange (server-to-server, X-API-Key)
        → Ticket wird atomar verbraucht (single-use) → Identität
      → RefBoard-Session-JWT wird gesetzt → weiter zum Task-Board

Beteiligte Komponenten:

Komponente Repo Aufgabe
RefBoard AYON (dieses Repo) Hermes/refboard-ayon Web-App: Canvas + Ticket-Auth + Task-Boards
AYON Server-Addon Hermes/refboard-addon (ab v0.2.0) Ticket-Ausstellung, /exchange, Launcher-Action
AYON Server (private Instanz) Identitätsquelle, Token-Prüfung, Access-Groups

Warum ein Ticket statt des AYON-Tokens in der URL?

Der AYON-Session-Token ist langlebig und dürfte nie in Browser-History/Logs landen. Das Ticket ist ein 32-Byte-Zufallswert, der genau einmal eingelöst werden kann und nach 60 s verfällt — die OAuth-"Code"-Äquivalenz. Die Identität kommt ausschließlich vom Addon (/exchange), niemals aus der URL.

Task-Boards

  • Adresse/Name: <project>/<task_path> (z. B. lumenfjord/assets/vegetation/fir/lookdev)
  • Board entsteht lazy beim ersten Öffnen in der Sammlung AYON
  • users-Tabelle bleibt intern bestehen (SQLite-Fremdschlüssel), wird aber nicht mehr als Login angezeigt; AYON-Nutzer bekommen Einträge <username>@ayon.local mit unbenutzbarem Passwort-Sentinel
  • Legacy-Login/Register-Routen sind noch vorhanden (für Alt-Instanz), im AYON-Betrieb jedoch ungenutzt

Deployment (orange)

  • Container: refboard-ayon, Host-Port 8003 → 8000
  • Stack-Ordner: /media/orange/RocketChat/refboard-ayon/ (NVMe)
    • repo/ — dieser Code (Branch ayon-integration)
    • compose.yaml — Stack (inkl. ayon-private_default external network: RefBoard erreicht AYON unter http://ayon-private-server-1:5000)
    • .envJWT_SECRET, REFBOARD_API_KEY, AYON_EXCHANGE_URL
    • data/ — SQLite + FS-Storage
  • nginx: /etc/nginx/sites-enabled/refboard.confrefboard.niklashmotion.art (WebSocket-Upgrade, 250 M Upload)
  • Wichtig nach docker compose up -d: das ayon-private_default-Netz ist als external: true deklariert und überlebt Rebuilds dadurch

Environment

Variable Bedeutung
JWT_SECRET Signatur-Secret der RefBoard-Sessions
REFBOARD_API_KEY Shared Secret für /exchange (muss mit dem AYON-Secret refboard_api_key übereinstimmen)
AYON_EXCHANGE_URL z. B. http://ayon-private-server-1:5000/api/addons/refboard/0.2.0/exchange
STORAGE_BACKEND fs (FS-Storage)
CORS_ORIGIN CORS-Origin (Default *)

Setup in AYON (Schritt für Schritt)

Ausführen, sobald refboard-0.2.0.zip und der A-Record existieren.

1. Addon installieren (im AYON-Klon, NICHT im Original)

# zip in den Server-Container entpacken
ssh orange@niklashmotion.art 'docker exec -i ayon-private-server-1 python3 -c "
import zipfile,io,os,sys
z=zipfile.ZipFile(io.BytesIO(sys.stdin.buffer.read()))
b=\"/addons/refboard/0.2.0\"
os.makedirs(b,exist_ok=True)
[open(os.path.join(b,n),\"wb\").write(z.read(n)) for n in z.namelist() if not n.endswith(\"/\")]
"' < refboard-0.2.0.zip

# AYON-Server neu starten (scannt /addons nur beim Start)
ssh orange@niklashmotion.art 'docker restart ayon-private-server-1'

2. Bundle (WebUI: Studio Settings → Bundles)

Neues Bundle anlegen, das die Addons des aktuellen Produktions-Bundles enthält, aber refboard: 0.2.0, und als Produktion aktivieren.

3. Settings prüfen (WebUI: Studio Settings → Addons → RefBoard)

  • refboard_url: https://refboard.niklashmotion.art
  • api_key: refboard_api_key (Secret existiert bereits im AYON-Secret-Store und muss denselben Wert wie REFBOARD_API_KEY in der RefBoard-.env haben)

4. Benutzen

  1. AYON-Launcher starten und ein Projekt öffnen
  2. Task auswählen → Kontext-/Aktionsmenü → „RefBoard öffnen"
  3. Browser geht auf, automatisch eingeloggt als der eigene AYON-User, im Board der Task
  4. Teilen: Kollegen wählen dieselbe Task → „RefBoard öffnen" → alle landen im selben Board und arbeiten in Echtzeit zusammen

Hinweise:

  • Der Board-Name ist <Projekt>/<Task-Pfad>; im Editor oben wird er als Titel angezeigt
  • Ohne Task-Auswahl gibt es keinen Action-Eintrag (Bewusst so gebaut: Boards sind taskbezogen)
  • Tickets sind einmalig und 60 s gültig — bei „Invalid or expired ticket" einfach im Launcher erneut klicken

AYON-REST-API des Addons (v0.2.0)

Alle Routen unter /api/addons/refboard/0.2.0/:

Endpoint Methode Auth Zweck
/health GET AYON-User Status + konfigurierte URL
/session POST AYON-User {project_name, task_id?}{url} (Ticket-URL)
/exchange POST X-API-Key {ticket}{ayon_user, display_name, project, task} (single-use)

Lokale Entwicklung / Tests

# Image bauen (ARM64-nativ auf orange getestet)
docker build -t refboard-ayon:latest .

# Container + Mock-Addon (Test-Double statt echtem AYON-Addon):
#   /media/orange/RocketChat/refboard-ayon/mock-exchange.js (container :9000)
#   /media/orange/RocketChat/refboard-ayon/e2e.sh           (Container-interner E2E)

Der E2E (Ticket-Ausstellung → Exchange → Board-Zugriff → Single-Use → 2. Nutzer am selben Board) ist mit dem Mock grün getestet.

Status: PRODUKTIV (seit 05.09.2026)

  • DNS + Let's-Encrypt-Zertifikat aktiv (refboard.niklashmotion.art)
  • Launcher-Klick → eingeloggt im Task-Board — produktiv im Einsatz

Fehler & Lektionen (Session 04.05.09.2026)

# Fehler Ursache Fix/Lektion
1 Launcher zeigte fast keine Actions mehr (KeyError: 'url' in _get_webactions) SimpleActionManifest(icon=…) erzeugte {"type":"url"} ohne url-Feld; eine einzige kaputte Action kippte alle Webactions im Client (try/except um den ganzen Fetch) Icon-Feld weggelassen; Lektion: Action-Icons brauchen {"type":"material-symbols","name":…} oder vollständige URL
2 /session → 500 AttributeError: 'UserAttribModel' object has no attribute 'name' AYON-User-attrib heißt fullName, nicht name user.attrib.fullName
3 Exchange → 500 uuidv4 is not defined Import im neuen db.js-Code vergessen Lektion: py_compile fängt undefined names nicht — Smoke-Test im Container statt nur Syntax-Check
4 RefBoard konnte AYON nicht erreichen nach compose up Externes Docker-Netz nur top-level deklariert, Service nicht attached; manuelles docker network connect überlebt kein Recreate Netz im Service-Block als external: true deklarieren
5 Exchange → 403 trotz „richtigem" Secret REFBOARD_API_KEY-Wert enthält =; Extraktion mit cut -d= -f2 bricht am ersten = → falscher (gekürzter) Wert in AYON-Secret Werte mit sed "s/^KEY=//" extrahieren; Lektion: Secret-Sync immer per Längen-/Hash-Vergleich verifizieren
6 Settings-POST (204) änderte die DB nicht AYON speichert Settings als Ganzes, filtert aber „identity"-Felder (Werte == Defaults) heraus — ein Feld, das dem Default entspricht, ist nie speicherbar Lektion: Settings-API ist Full-Replace + Identity-Filter; gezielte Feld-Fixe über die API sind nicht immer möglich
7 App-Kacheln fehlten in jeder Task (Launcher leer bis auf 3 Actions) Ynput-Bug in applications 1.4.4: Runtime liest Pydantic-Defaults (profiles=[]), nicht DEFAULT_VALUES (mit all_applications-Profil); das UI zeigt die Defaults trotzdem — Diskrepanz UI/Runtime Umgehend: Profil per API explizit setzen (Full-Replace aus Backup + Profil-Feld); langfristig: Ynput-Issue
8 Ticket-Wiederverwendung zeigte 502 statt 401 RefBoard behandelte 401/403 vom Addon als Infrastruktur-Fehler 401/403 aus /exchange → sauberes 401 „Invalid or expired ticket"
9 Nach Secret-Löschung + Neuanlage Exchange-Fehler AYON-Secret-Wert ≠ Container-Env (Container läuft mit altem Env bis Recreate) Nach Secret-Änderungen: docker compose up -d --force-recreate

Noch offen

  • A-Record ✓ erledigt (05.09.)
  • Zertifikat ✓ erledigt (05.09.)
  • Nuke-17.0-Pfad-Mismatch in den Applications-Settings (/usr/local/Nuke17.0v1 erwartet, installiert ist /opt/Nuke17.0v3) — Fix im Studio-Settings-WebUI: Executable auf /usr/local/bin/nuke-ayon setzen
  • Alt-Container refboard (:8002, standalone) stilllegen, sobald Bestands- Boards nicht mehr gebraucht werden
  • Ynput-Issue zu #7 (applications 1.4.4 Runtime-Defaults) optional melden