Files
Onyscribe-Admin/docs/RUNBOOK_PARALLELTEST.md

19 KiB
Raw Permalink Blame History

Runbook: Admin-Plattform parallel zum Altbetrieb testen (ohne Merge, nur mit Demo-Tenant)

Ziel: Die neue Admin-Plattform und den neuen Core parallel zu den laufenden Tenants betreiben – mit einem neuen Test-Tenant demo-admin. Nichts Bestehendes wird angefasst, es wird nichts gemergt, und jeder Schritt lässt sich einzeln zurücknehmen.


0. So läuft das Ganze parallel (und warum der Altbetrieb sicher ist)

ALTBETRIEB (unverändert)                           NEUBETRIEB (Test)
────────────────────────                           ─────────────────
Gitea: main / cortecs-llm-migration                Gitea: Branch admin-platform-integration
  └ build-deploy.yml → :latest + deploy-all          └ build-branch-image.yml → NUR Image :<sha>  (kein :latest, kein Deploy)
Mittwald: app-demo, app-rotary, app-sprinz, …      Mittwald: app-demo-admin   ← neuer, eigener Service + Volume + Ingress
  Domain: demo.<DOMAIN> …                            Domain: demo-admin.<DOMAIN>
  Daten: ins Image gebacken (tenants/)               Daten: Bundle von der Admin-Plattform (TENANT_SOURCE=admin)
  OIDC-Client: von Hand angelegt                     OIDC-Client: automatisch über die Login-API
                                                    Admin-Plattform auf Coolify (eigene Domain, eigene Postgres)

Schutzmechanismen (alle eingebaut und getestet):

Schutz Wirkung
Branch-Trennung build-deploy.yml läuft nur auf main/cortecs-llm-migration (auch nicht per „Run workflow“ vom Test-Branch). Der Test-Branch baut nur ein Image mit Tag = Git-SHA.
Eigener Tenant demo-admin hat eigenen Service app-demo-admin, eigenes Volume vol-demo-admin, eigenen Host und eigenen OIDC-Client. app-demo bleibt unberührt.
DEPLOY_ALLOWED_TENANTS=demo-admin Die Admin-Plattform darf nur diesen Tenant live anfassen (Mittwald und Login-API). Auch „Alle neu deployen“ trifft nur ihn.
DEPLOY_LIVE=false zum Start Erst nur Dry-Run (liest den Stack, schreibt nichts).
Differenzielles PATCH + Guard Es wird nur app-demo-admin geschrieben; danach prüft der Admin, dass alle fremden Services noch da sind.
Default TENANT_SOURCE=git im Core Der neue Core verhält sich ohne Env wie der alte.

Rückgängig machen: siehe Abschnitt 11.


1. Werte zusammentragen (einmalig)

Wert Woher Verwendung
DOMAIN Gitea → Repo transkriptipt-platform → Einstellungen → Actions → Variablen Basis-Domain in der Admin-Plattform
PROJECT_ID, STACK_ID dito Mittwald-Ziel
REGISTRY (z. B. gitea.onyva.dev/onyva) dito Registry in der Admin-Plattform
MITTWALD_API_TOKEN Gitea → Secrets (du kennst den Wert; derselbe Token) Env der Admin-Plattform
Weitere Variablen: OIDC_ISSUER, AUTH_ENABLED, APP_COOKIE_SECURE, MAX_FILE_SIZE_MB, CORTECS_BASE_URL, LLM_MODEL, LLM_MAX_TOKENS, LLM_TEMPERATURE, SMTP_HOST/PORT/USER/FROM, MISTRAL_*, COST_* dito in Einstellungen der Admin-Plattform (Abschnitt 6)
CORTECS_API_KEY, SMTP_PASSWORD cd ~/PycharmProjects/transkript-platform && sops -d --extract '["CORTECS_API_KEY"]' secrets/shared.enc.yaml (analog SMTP_PASSWORD) Einstellungen → Geteilte Secrets
COST_INGEST_KEY von demo sops -d --extract '["COST_INGEST_KEY"]' tenants/demo/secrets.enc.yaml Secret des Test-Tenants (Abschnitt 7, Punkt 7.4)
<ADMIN_HOST> du wählst: Domain, unter der Coolify die Admin-Plattform ausliefert, z. B. admin.deine-domain.de muss öffentlich per HTTPS erreichbar sein (der Tenant-Container holt von dort sein Bundle)
<DEINE_MAIL> deine Login-E-Mail bei login.onyva.dev (Konto muss dort existieren) Admin-Zugriff + Freigabe im Test-Tenant

Werte nicht in Chats oder Tickets kopieren (Keys, Secrets).


2. Core-Branch pushen (Image bauen lassen)

cd ~/PycharmProjects/transkript-platform
git branch --show-current          # → admin-platform-integration
git log --oneline -3               # 13055b8 CI: build-deploy nur von Produktions-Branches …
git rev-parse HEAD                 # → voller SHA; z. B. 13055b811ca0030841f41ce1f10e4f30cba1a7db  ← MERKEN (= CORE_SHA)
git push -u origin admin-platform-integration

Was jetzt in Gitea passiert (Repo → Actions):

Workflow Erwartung
test grün (Schema ↔ Code ↔ Tenants, Bundle-Loader)
build-branch-image grün; Log-Zeile „Image gebaut: <registry>/transkript-platform:<SHA>“
build-deploy läuft nicht (Branch nicht gelistet) – wenn doch: sofort abbrechen und melden

Prüfen: Gitea → Repo → Packages → transkript-platform hat einen neuen Tag = voller SHA. Der Tag latest ist unverändert (Zeitstempel!).

✅ Ergebnis: CORE_SHA (voller 40-stelliger SHA). Lege ihn in deine Notizen.


3. Admin-Plattform ins eigene Repo

  1. Gitea → Neues Repository: Organisation Onyva, Name onyscribe-admin, privat, leer (ohne README/.gitignore/Lizenz).
  2. Lokal:
cd ~/PycharmProjects/onyscribe-admin
git status --short | head                # .env und .data dürfen NICHT erscheinen (sind ignoriert)
git ls-files | grep -E '(^|/)\.env$|\.db$' || echo "ok: keine Secrets/DB im Index"
git add -A
git commit -m "Onyscribe Admin: Initialer Stand"
git remote add origin https://gitea.onyva.dev/Onyva/onyscribe-admin.git
git push -u origin main

Hinweis: seed/tenants.seed.json.gz enthält die Tenant-Konfigurationen inkl. Zusatzdateien (z. B. namensliste.txt – personenbezogen). Das liegt heute schon im Altrepo; Repo privat halten.


4. Login-System: Client + API-Key für die Admin-Plattform

Im Login-Dashboard (login.onyva.dev), als Admin:

  1. API-Keys → neuer Key („onyscribe-admin“, ggf. Ablaufdatum). Klartext onyva_… einmalig kopieren → später ONYVA_LOGIN_API_KEY.
  2. Client für die Admin-Plattform selbst anlegen (Dashboard oder per API):
KEY=onyva_…                         # der Key aus 1.
curl -sX POST https://login.onyva.dev/api/v1/apps -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"name":"Onyscribe Admin","redirect_uris":["https://<ADMIN_HOST>/auth/callback"],"auth_mode":"required","totp_mode":"disabled"}'
# → client_id + client_secret SOFORT sichern (nur einmal sichtbar)
curl -sX PUT https://login.onyva.dev/api/v1/apps/<client_id>/memberships -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"user_email":"<DEINE_MAIL>","role":"admin"}'

Ergebnis: client_id, client_secret (Admin-Login), ONYVA_LOGIN_API_KEY.


5. Coolify: Admin-Plattform deployen

Neue Ressource → Docker Compose (aus Git): Repo Onyva/onyscribe-admin, Branch main, Compose-Datei docker-compose.yml (Zugriff auf das private Repo per Deploy-Key/Token einrichten).

Umgebungsvariablen (Coolify → Ressource → Environment):

Variable Wert Phase
POSTGRES_PASSWORD langes Zufallspasswort immer
SECRET_KEY python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" – sichern! ohne ihn sind die Secrets in der DB unlesbar immer
AUTH_ENABLED true immer
OIDC_ISSUER https://login.onyva.dev immer
OIDC_CLIENT_ID / OIDC_CLIENT_SECRET aus Abschnitt 4 (Punkt 2) immer
OIDC_REDIRECT_URI https://<ADMIN_HOST>/auth/callback immer
OIDC_LOGOUT_REDIRECT_URI https://<ADMIN_HOST>/ immer
APP_COOKIE_SECURE true immer
ADMIN_ALLOWED_EMAILS <DEINE_MAIL> (weitere kommagetrennt) immer – ohne Regel wird jeder Login abgelehnt
MITTWALD_API_TOKEN derselbe Token wie in Gitea immer
ONYVA_LOGIN_API_KEY aus Abschnitt 4 (Punkt 1) immer
DEPLOY_ALLOWED_TENANTS demo-admin immer
DEPLOY_LIVE false Phase 1 (Dry-Run) → in Abschnitt 8 auf true
OIDC_SYNC_LIVE false optional true, um den Login-Abgleich separat vor dem Deploy zu testen
CORE_RELEASE_TOKEN leer erst in Abschnitt 10
CORTECS_API_KEY leer (wird in der UI als Secret gesetzt) optional

Domain: Service admin → Domain https://<ADMIN_HOST>:8300 (Port 8300 = Container-Port). Persistente Daten: Volume pgdata (Postgres) – Backup einrichten.

Deploy starten. Der erste Build nutzt das normale Dockerfile (mitgelieferter Core-Snapshot, keine Registry nötig).

Prüfen:

  • https://<ADMIN_HOST>/healthz → {"ok":true}
  • https://<ADMIN_HOST>/ → Weiterleitung zu login.onyva.dev → Login → Dashboard mit 7 Tenants (Seed).
  • Seitenleiste unten: „Deploy: gesperrt · Dry-Run“, „<DEINE_MAIL>“.
  • https://<ADMIN_HOST>/auth/me zeigt "auth_enabled": true. Steht dort false (Seitenleiste: rot „Login aus – offen!“), ist die Plattform für jeden offen: AUTH_ENABLED=true (ohne Anführungszeichen) und die OIDC-Variablen prüfen. Ohne Login sind Live-Aktionen automatisch gesperrt.
  • Probleme: „Kein Zugriff“ → ADMIN_ALLOWED_EMAILS; redirect_uri-Fehler → Redirect-URI im Login-Client exakt wie in OIDC_REDIRECT_URI.

6. Admin-Plattform konfigurieren (Menü „Einstellungen“)

Felder (Spalte „Gitea“ = dieselbe Variable wie bisher), dann oben „Alles speichern“:

Feld in der Admin-Plattform Wert / Gitea
Basis-Domain DOMAIN
Mittwald PROJECT_ID / STACK_ID PROJECT_ID / STACK_ID
Registry REGISTRY
Image-Name transkript-platform
Öffentliche URL der Admin-Plattform https://<ADMIN_HOST>
Core kann Bundle laden ✔ aktivieren (betrifft nur Tenants mit Quelle „Admin“, also nur demo-admin)
Login (OIDC) & Limits OIDC_ISSUER, AUTH_ENABLED (true), APP_COOKIE_SECURE (true), MAX_FILE_SIZE_MB
LLM & Transkription CORTECS_BASE_URL, LLM_MODEL, LLM_MAX_TOKENS, LLM_TEMPERATURE, MISTRAL_*
E-Mail (SMTP) SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_FROM
Kostenerfassung COST_API_BASE, COST_TRACKING_ENABLED
„Weitere Core-Einstellungen“ (aus dem Schema) nur ausfüllen, was du in Gitea auch gesetzt hast (COST_LLM_*, COST_STT_PER_MINUTE, STT_* …); leer = Standard des Cores
Rollout → Canary-Tenants demo-admin
Geteilte Secrets → CORTECS_API_KEY Wert setzen (aus sops -d …)
Geteilte Secrets → SMTP_PASSWORD Wert setzen (nur nötig, wenn der Test E-Mail-Versand prüfen soll)

Dann: Karte „Login-API“ → „Verbindung testen“ → ✔ Verbindung ok – N App(s) im Login.


7. Test-Tenant demo-admin anlegen und konfigurieren

7.1 Anlegen: Dashboard → + Neuer Tenant → Name Onyva Demo (Admin-Test), ID demo-admin, Ausgangspunkt „Kopie von Onyva Demo“ → Anlegen. (Quelle ist automatisch „Admin“, OIDC-Verwaltung „managed“.)

7.2 Spracherkennung: Tenant → Funktion & STT → Provider cortecs, Modell voxtral-mini-transcribe-2602 (dann reicht der geteilte Cortecs-Key; demo nutzt sonst Mistral und bräuchte einen eigenen MISTRAL_API_KEY).

7.3 Optisch unterscheidbar machen: Marke & Farben → Akzent z. B. #E8590C → „Töne aus Akzent ableiten“. Oben rechts Prüfen & veröffentlichen → Nachricht „Test-Tenant“ → v2.

7.4 Secrets: Tenant → Secrets → COST_INGEST_KEY Wert setzen (der Wert von demo; Kosten laufen dann unter demo, für den Test okay). SESSION_SECRET und ADMIN_BUNDLE_TOKEN sind schon erzeugt. OIDC_CLIENT_ID/SECRET legt der Deploy automatisch an.

7.5 Login: Tenant → Domain & Login: Subdomain demo-admin; OIDC-Verwaltung managed, Zugriff required; Freigaben: <DEINE_MAIL> als editor (Nutzer muss im Login existieren) → Speichern. „Gegen Login prüfen“ (nur lesend) → erwartet: „würde App ‚Onyscribe – Onyva Demo (Admin-Test)‘ anlegen (Redirect: https://demo-admin./auth/callback …)“ und „würde <DEINE_MAIL> als editor freigeben“.

7.6 Core pinnen: Tenant → Übersicht → Karte „Core-Version“ → Pin = voller SHA aus Abschnitt 2 → Pin setzen. (Der Pin sorgt dafür, dass genau das Branch-Image läuft und der Health-Check die Core-Version prüfen kann.)

7.7 Vorflug-Check + Dry-Run: Tenant → Deploy → Vorflug-Check → Prüfen. Erwartet in Phase 1: alles grün/gelb, gelb nur „DEPLOY_LIVE nicht aktiv“; keine roten Punkte. Typische rote Punkte und Fix stehen direkt dabei (z. B. Registry/PROJECT_ID/Token fehlen, CORTECS_API_KEY/COST_INGEST_KEY fehlen, „Core kann Bundle laden“ aus, Admin-URL nicht erreichbar). Dann Dry-Run → Log lesen: „geschützte bestehende Services (bleiben unangetastet): [app-demo, app-rotary, …]“, [DRY-RUN] PATCH … für Volume und Service, kein Schreibzugriff.


8. Live-Deploy des Test-Tenants

  1. Coolify → Admin-Ressource → DEPLOY_LIVE=true setzen (DEPLOY_ALLOWED_TENANTS=demo-admin bleibt) → neu deployen (Daten bleiben).
  2. Admin → demo-admin → Deploy → Vorflug-Check → muss „Bereit“ zeigen → Deployen.

Was passiert (Log): OIDC-Client im Login anlegen und Secret speichern → Pflicht-Secrets prüfen → Volume + Service per PATCH → Service neu erzeugen → Ingress demo-admin.<DOMAIN> → Health-Check (bis ~90 s Wartezeit für Start + Zertifikat).

Abnahme-Checkliste:

  • Deploy-Log endet mit Health-Check … ✔ · Core 13055b811c · Bundle v2 und ✔ Fertig
  • mStudio: Service app-demo-admin läuft; alle anderen Services unverändert (Image-Tags wie vorher)
  • https://demo-admin.<DOMAIN>/health → core.version = dein SHA, bundle = {"source":"admin","version":2,"stale":false}
  • Seite öffnen → Login → freigegebener Nutzer kommt rein → Oberfläche in der neuen Farbe
  • Protokoll erzeugen (kleines Transkript hochladen) → Zusammenfassung → PDF/Word → Aussehen = Vorschau in der Admin-Plattform
  • Admin → Dashboard → Zustand prüfen: demo-admin grün. Die Altbetrieb-Tenants zeigen „Core ohne Vertrag (alte Version)“ – erwartet und harmlos (sie laufen noch auf dem alten Image)
  • Altbetrieb: demo.<DOMAIN> und die anderen Kunden funktionieren unverändert

9. Änderung ohne Core-Änderung testen

  1. Admin → demo-admin → Marke & Farben: Akzent ändern → Prüfen & veröffentlichen (v3) → Deploy → Deployen (nur Neustart, kein Image-Build).
  2. Erwartung: Health-Check Bundle v3 ✔; Seite neu laden → neue Farbe.
  3. Agent: KI-Agent → „Setze die Akzentfarbe auf #0B6E4F“ → Live-Vorschau beobachten → „In Entwurf übernehmen“ → veröffentlichen → deployen.
  4. Ausfallsicherheit (nur demo-admin!): Coolify → Admin-Ressource stoppen; in mStudio den Container app-demo-admin neu starten → er startet mit gecachtem Bundle: https://demo-admin.<DOMAIN>/health → bundle.source = "cache", stale = true. Admin wieder starten → nächster Container-Neustart holt wieder admin.

10. (Optional) Den kompletten Core-Release-Weg testen

  1. Coolify: CORE_RELEASE_TOKEN = langes Zufallstoken, Admin neu deployen. Gitea → Repo → Einstellungen → Actions: Variable ADMIN_URL = https://<ADMIN_HOST>, Secret ADMIN_RELEASE_TOKEN = dasselbe Token. (Wirkt nur auf Workflows des Test-Branches; main kennt den notify-admin-Job nicht.)
  2. Im Core-Repo eine Kleinigkeit committen und auf den Branch pushen → build-branch-image baut und meldet das Release.
  3. Admin → Menü Core: neues Release, Badge „Admin älter/anders“ (die Admin-Plattform enthält noch den alten Core-Snapshot).
  4. Angleichen: cd ~/PycharmProjects/onyscribe-admin && scripts/sync_core.sh && git add -A && git commit -m "Core-Snapshot aktualisiert" && git push → Coolify deployt → Badge „gleicher Core“. (Später ersetzt Dockerfile.fromcore diesen Schritt: Admin wird direkt auf dem Core-Image gebaut.)
  5. Prüfen → Matrix mit allen 7 Tenants (beim ersten Mal „neu (keine Baseline)“) → Freigeben → Dry-Run → Tenant demo-admin: Pin aufheben → Ausrollen → nur demo-admin wird live ausgerollt (Allowlist), Health-Check prüft die neue Core-SHA.
  6. Rollback testen: Zurückrollen (stellt den vorherigen Tag wieder her).

11. Abbruch / Rückbau (jederzeit)

Was Wie
Test-Tenant live entfernen Admin → demo-admin → Übersicht → Gefahrenbereich → Offboard-Dry-Run prüfen → Offboard (live) (entfernt Service, Volume, Ingress)
OIDC-Client des Test-Tenants Gefahrenbereich → OIDC-Client im Login löschen
Admin-Plattform Coolify-Ressource stoppen/löschen; Login-Client „Onyscribe Admin“ und API-Key im Login löschen
Branch/Image Gitea: Branch admin-platform-integration löschen, Package-Tag (SHA) löschen
Alles Live sperren DEPLOY_LIVE=false (und/oder DEPLOY_ALLOWED_TENANTS leeren) → Admin neu deployen

Der Altbetrieb braucht in keinem dieser Fälle eine Änderung.


12. Fehlersuche

Symptom Ursache / Fix
Vorflug: „Mittwald-Stack lesbar“ rot Token-Rechte, PROJECT_ID/STACK_ID in Einstellungen prüfen (dieselben Werte wie Gitea)
Deploy: „Pflicht-Secrets ohne Wert: …“ CORTECS_API_KEY (Einstellungen → Geteilte Secrets), COST_INGEST_KEY (Tenant → Secrets), ggf. MISTRAL_API_KEY (nur bei STT-Provider mistral)
Deploy: „… nicht für Live-Schreibzugriffe freigegeben“ DEPLOY_ALLOWED_TENANTS enthält die Tenant-ID nicht
Deploy: „Quelle ‚Admin‘ ist noch gesperrt“ Einstellungen → „Core kann Bundle laden“ aktivieren
Deploy: „OIDC-Abgleich fehlgeschlagen: API-Key ungültig (401)“ ONYVA_LOGIN_API_KEY falsch/abgelaufen; Key im Login neu erzeugen
Deploy: „… Freigaben: existiert im Login nicht“ (Warnung) Nutzer im Login anlegen, dann Domain & Login → Jetzt abgleichen
Health-Check: „Core X statt Y“ Pin/Tag stimmt nicht mit dem Image überein oder Image fehlt in der Registry (mStudio-Container-Log)
Health-Check: „Bundle cache v… (veraltet)“ Container erreicht die Admin-URL nicht: Domain/HTTPS/Firewall, admin_public_url, Bundle-Token
Container-Log: „Tenant-Bundle … nicht verfügbar“ wie oben; zusätzlich ADMIN_URL/ADMIN_BUNDLE_TOKEN im Plan (Deploy → Service-Definition) prüfen
Login der Tenant-Seite: redirect_uri-Fehler Domain & Login → Gegen Login prüfen → Jetzt abgleichen (ergänzt die Redirect-URI)
Login: invalid_client OIDC_CLIENT_SECRET fehlt/ist veraltet → Jetzt abgleichen bzw. neu deployen
Zertifikat/Ingress fehlt Token braucht Domain/Ingress-Recht (Log: „Ingress … NICHT angelegt“); Service läuft trotzdem, nach Rechteänderung erneut deployen
Admin „Zustand prüfen“: „nicht erreichbar“ Tenant noch nicht deployt bzw. DNS/Zertifikat noch nicht fertig

13. Danach (nicht Teil dieses Tests)

Erst wenn der Test-Tenant mehrere Tage sauber läuft: Core-Branch reviewen und mergen (→ build-deploy baut dann den neuen Core für alle), Secrets der echten Tenants importieren (python scripts/import_tenants.py --with-secrets), pro Tenant die Cut-over-Checkliste abarbeiten und DEPLOY_ALLOWED_TENANTS schrittweise erweitern. Die echten Tenants stellst du einzeln um – Rückweg: Quelle zurück auf „Git“.