Changelog
aktuelle Version v1.4.3
Chronologische Dokumentation der Änderungen (neueste zuerst). Jede Zeile
entspricht einem deployten Git-Commit auf main. Audit-Findings + gemeldete
Bugs, die noch nicht gefixt sind, stehen als GitHub-Issue-Nummern dabei.
Versionierung: Semver über Git-Tags (vX.Y.Z). Veröffentlichte Versionen
stehen unten mit ## vX.Y.Z-Überschrift; ältere Einträge (vor Einführung der
Tags) sind nach Datum gruppiert. Diese Datei ist die Quelle der öffentlichen
Seite /changelog.
v1.4.3 — 2026-09-09
Behoben
- HTML-Codes in Artikel-Titeln: Titel aus WordPress zeigten
Conversion Hero – Online Wiederkäufe sichernstatt des Gedankenstrichs. WordPress liefert typografische Zeichen als HTML-Codes; die wurden unverändert übernommen. Betroffen waren 2.880 Titel über zehn Publikationen — alle sind korrigiert, und neue werden beim Abgleich richtig übernommen. Nebenbei behoben: eine Hilfsfunktion ersetzte solche Codes durch Leerzeichen, ausTipps & Trickswurde alsoTipps Tricks. - Generierte Bilder von passwortgeschützten Seiten (#765): Bilder, die die Pipe erzeugt und nach WordPress hochgeladen hat, wurden in der Mediathek als „nicht ladbar" angezeigt. Ihre Adresse zeigt nach dem Hochladen auf WordPress — und liegt die Seite hinter einem Passwortschutz, kam auch hier eine Fehlermeldung statt des Bildes. Wird jetzt mit den hinterlegten Zugangsdaten geholt, wie die Vorschaubilder in der Artikel-Liste.
v1.4.2 — 2026-09-09
Behoben
- Aufmacherbilder von passwortgeschützten Seiten (#765): Liegt eine WordPress-Seite hinter einem Passwort-Dialog des Webservers, sind auch ihre Bilder geschützt — der Browser schickt beim Laden eines Bildes keine Zugangsdaten mit und bekam eine Fehlermeldung statt des Bildes. Die Vorschaubilder blieben deshalb leer. Sie werden jetzt über den Server geholt, der die hinterlegten Zugangsdaten kennt. Nur für Seiten mit Passwortschutz — alle anderen laden weiter direkt.
v1.4.1 — 2026-09-09
Behoben
- Filter und Tabs reagieren sofort (#776): Ein Klick auf ALLE/Beiträge/Seiten oder auf einen Kategorie-Filter änderte nur die Adresse — die Seite zeigte bis zur Antwort des Servers unverändert die alte Liste, ohne jedes Zeichen, dass der Klick angekommen war. Die Auswahl schaltet jetzt im selben Moment um, und ein Ladehinweis zeigt, dass gearbeitet wird.
- Artikel-Liste deutlich schneller (#778): In der Datenbank stehen nur die Kennungen der Kategorien und Schlagwörter, nicht deren Namen — die wurden daher bei jedem Seitenaufbau von WordPress nachgeladen, mit Wartezeit, und bei jedem Filterklick erneut. Die Namen kommen jetzt beim WordPress- Abgleich mit und liegen in der eigenen Datenbank; die Liste fragt WordPress nur noch, wenn nie abgeglichen wurde. Die Abfrage selbst dauert 2,5 ms.
- Kopfzeile verrutschte nach „Aus WordPress aktualisieren" (#777): Die Bestätigungsmeldung stand in derselben Zeile wie der Button und schob den Seitenkopf auseinander. Sie steht jetzt in einer eigenen Zeile.
v1.4.0 — 2026-09-09
Neu
- Mitglieder entfernen und Einladungen zurückziehen (#766): Die Team-Verwaltung konnte bisher nur hinzufügen. Jetzt lässt sich pro Zeile ein Mitglied entfernen (der Zugang ist sofort weg, der Account bleibt bestehen) und eine offene Einladung zurückziehen — dabei wird der Einladungslink ungültig, nicht bloß unsichtbar. Zwei Sperren zum Schutz: niemand kann sich selbst entfernen, und der letzte Admin bleibt.
- Sites hinter Passwortschutz anbindbar (#765): Liegt eine WordPress-Seite hinter einem Passwort-Dialog des Webservers (Staging-Boxen, Wartungsmodus), ließ sich sie bisher nicht verbinden — der Verbindungstest scheiterte an der Tür, bevor WordPress überhaupt gefragt wurde. Unter Einstellungen → WordPress lassen sich die Zugangsdaten der Tür jetzt getrennt vom WordPress-Zugang hinterlegen; die Anmeldung bei WordPress läuft dann über das Companion-Plugin.
Behoben
- Quellen aus dem Themen-Explorer kamen im Compose-Bereich nicht an (#767): Zwei Drittel aller Quellen eines Themas wurden auf dem Weg stillschweigend verworfen — betroffen waren Verweise ohne eigene Adresse, also Bezüge auf eigene Artikel und Begründungen des Modells. Zudem standen die übergebenen Adressen nur im Eröffnungstext des Briefings und wurden nicht als Recherche-Vorgabe an die Erstellung weitergegeben. Beides behoben.
- Irreführende Fehlermeldung bei gesperrten Seiten (#765): Ein 401 des Webservers wurde als WordPress-Anmeldefehler gemeldet und schickte damit zu den Zugangsdaten, an denen nichts falsch war. Die beiden Fälle werden jetzt unterschieden und benannt.
- SEO-Felder erreichten Yoast/RankMath nicht (#743): Ohne Companion-Plugin nahm WordPress die SEO-Angaben stumm nicht an und antwortete trotzdem mit Erfolg. Das wird jetzt erkannt und protokolliert; die Veröffentlichung selbst bleibt davon unberührt.
- Geplante und zur Prüfung vorgelegte Beiträge sahen wie Entwürfe aus
(#743): Beim Abgleich mit WordPress wurden
future,pendingundprivatealle zu „Entwurf". Terminierte Beiträge erscheinen jetzt als „Geplant", vorgelegte als „In Prüfung". - Nächtlicher WordPress-Abgleich brach bei langsamen Seiten ab: Das Zeitlimit für das Abholen ganzer Beitragsseiten war zu knapp — bei mehreren Publikationen scheiterte der Abgleich jede Nacht. Limit angehoben.
- Wissen & Fakten aufgeräumt (#718): Der Bereich stapelte sechs Blöcke untereinander. Ein doppelter Hinweis ist entfallen, „Per Chat erfassen" liegt jetzt dort, wo auch Dateien hinzugefügt werden.
v1.3.1 — 2026-09-03
Behoben
- Translate nutzte veraltete Quellversion (#762/#763): Der Editor speicherte bei manuellen Änderungen nur die HTML-Fassung, nicht die Markdown-Fassung — Übersetzungen basierten dadurch auf einem alten Stand, obwohl online schon die überarbeitete Version stand. Beide Fassungen werden jetzt beim Speichern konsistent gehalten.
- Interne Verlinkung bei veröffentlichten Beiträgen (#761): Gleiche Ursache — die Verlinkung suchte im veralteten Text und fand nichts. Mit dem Fix greift sie auch bei veröffentlichten Beiträgen.
- KI-„Denk"-Text im Änderungsvorschlag (#760): Interne Reasoning-Blöcke mancher Modelle wurden im Editor-Vorschlag angezeigt. Werden jetzt zentral herausgefiltert.
- Bild-Backfill-Werkzeug (#746): Zwei Bugs im Wartungsskript korrigiert (Rechte-Kontext + Ergebnis-Auslesen); tote Alt-Bild-URLs werden nun korrekt erkannt.
v1.3.0 — 2026-09-02
Neu
- Öffentliche Changelog-Seite (
/changelog): diese Übersicht ist jetzt ohne Login untercontent-pipe.calluna.ai/changelogerreichbar. Statisch zur Build-Zeit aus dieser Datei gerendert, mit Anzeige der aktuellen Version. Versionsmanagement per Semver + Git-Tags.
2026-09-01
Deployed auf Prod (content-pipe.calluna.ai)
- CI-Lint-Fix (
fix(ci)):<a>→<Link>inLibraryLanguageSetting— behob den chronisch roten CI-validate-Job (no-html-link-for-pages-Error). - Translate: Versionshistorie + Rollback (#754) — spiegelt die Artikel-
Versionierung auf
translate.translations. Migration 0065 (translation_versions, Voll-Snapshot title/content/metadata/status/ccqs, FORCE RLS im 0055-Muster, GRANTs ancontent_pipe_rtfür #738). Kanonischer Writersrc/lib/translate/versioning.ts; Snapshots bei generate/translate/ edit/fix_note/rollback (Baseline v1 bei erster Generierung); Rollback-Route (Voll-Restore, append-only, 30/h); Versions-List/Detail-API; UITranslationVersionsPanel(Label + Actor, Diff gegen Vorgänger). Von einem Implementierungs-Agenten gebaut, Migration/Rollback reviewt, 170 Tests grün. - #734 Translate-Retry-Doppelkosten:
translateQueueattempts=1 (statt Default 3). Ein Job fährt die nicht-resumable LLM-Pipeline; BullMQ-Retry zahlte Spend 2–3× + konnte Auto-Publish doppeln. callLLM retryt transiente Fehler eh intern (#537/#493). - Translate SEO-Suggest-Guard: 409 wenn Übersetzungstext leer (statt verschwendetem LLM-Call + irreführender „Keine Kandidaten").
Audit-Batch (4 parallele Agenten, gebündelt deployed, e5621c9)
- #741 Cast-Guards: CASE-Guard (regex) an 8 Runtime-Cast-Sites — malformed/
leerer
metadata.wp.cmsPostId/date-Wert wird NULL statt 22P02-Throw (blockte Writes / 500te Reads über alle Tenant-Rows). Follow-up: Index-Expression in 0040. - #736 Entitlement-Gate:
requireInsightTenantgated 11 Insight/Trends-APIs (DataForSEO/LLM-Budget) — nicht-berechtigte Tenants können sie nicht mehr direkt aufrufen (CLAUDE.md-Prinzip 7). - #750 Übersetzte Kategorien/Tags: Term-Namen → Zielsprache (gecacht) + im Editor angezeigt (Label + Original klein); Cross-Domain-Publish mappt auf Ziel-WP-Term-IDs (find-or-create); same_site = ID-Erhalt.
- #740 Web-Search-Budget: Suchgebühr fließt jetzt in
total_cost_cents→checkBudgetzählt sie mit (unterzählte sie vorher).
Sequenzieller Deploy (App→Worker) nötig — paralleler Doppel-Build OOM'te den
Build-Container (23 GB Box, zwei gleichzeitige next build = Speicher-Spike).
- #749 Wasserzeichen für WP-Mediathek-Bilder: neuer Endpoint
POST /api/cms/media/[id]/label— lädt die WP-Media-Bytes (SSRF-safe viafetchMediaById+ safeFetch), rendert das EU-Icon (sharp) rein und lädt es als NEUES WP-Medium hoch (Original unangetastet). Lightbox-„Gekennzeichnete Kopie erstellen" für WP-Bilder (one-shot, kein Toggle). Rate-Limit 30/h.
Bug-Batch (7 parallele Agenten, gebündelt deployed, 3367189)
- #744 GSC-Admin-Liste: gruppiert nach Domain wie die Publikationsliste
(statt pro-Tenant/aktiv-only/nach Name) —
groupPublications. - #745 Kategorie-Namen: Browser-User-Agent im WP-Taxonomy-Fetch (reduziert WAF-403) + UI-Fallback „Kategorie #N" statt roher Zahl.
- #747 Trends-Duplikate: ON-CONFLICT-Upsert + DISTINCT-Anzeige + Migration 0066 (Unique-Index, Dedup bestehender Rows, content_pipe_rt-GRANTs).
- #748 „eingeladen"-Geist: Pending-Invites von bereits-Mitgliedern werden in der Team-Liste ausgeblendet.
- #752 Translate-QA: nur echte behebbare Fehler in der Fix-Liste (Lob + quellen-bedingt raus) + Trunkierungs-Längen-Ratio-Guard. Score unverändert.
- #753 UX: „Besprechen"-Panel scrollt beim Öffnen in den Sichtbereich.
- #737 Rollback-Datenverlust: Text-Rollback nutzt /rollback (Voll-Snapshot inkl. contentHtml) → manuelle Formatierung bleibt erhalten. Follow-up: HTML→MD beim Editor-Save.
Wave-1-Batch (5 parallele Agenten, gebündelt deployed, b7bc6bf)
- #756 Publish→Entwurf: 10min-Publish-Grace verhindert, dass der Status-Sync einen frisch publizierten Artikel auf draft zurücksetzt (WP-Read-Lag). →#757.
- #738 GRANTs: Migration 0067 macht content_pipe_rt self-sufficient (public+translate, inkl. ALTER DEFAULT PRIVILEGES) — schließt die 42501-Klasse.
- #739 CCQS-Scorer: hasProperNounSignal statt kaputter Regex (dt. Großschreibung) → concreteness/engagementHook diskriminieren wieder (Scores verschieben sich bei künftigen Bewertungen; Gate unverändert).
- #731 Brand-Timeout: 45s Per-Call-Timeout auf /api/brand/chat + writing-chat + sauberer 504. →#758.
- #664 Halluzinierte Statistiken: Seed-Prompt-Regel + Headline-Detektor (Slop-Weakness, Score 0). Live-DB-Prompt braucht die Regel noch via Admin.
Wave-2-Batch (4 parallele Agenten, gebündelt deployed, e77998c)
- #735 Publish-TX: Route in 3 Phasen (Read-TX → WP-I/O ohne offene TX → Write-TX) + 20s-Timeouts → keine Pool-Exhaustion durch hängende WP-Hosts.
- #742 Feed-Discovery: nackte Domain → robots.txt/
<link rel=alternate>/ Standard-Pfade automatisch entdecken + als Feed ingesten. - #730 lokale-Edits-Clobber: WP-Sync überschreibt lokalen Content nicht mehr,
wenn
articles.updatedAtneuer als WPmodified_gmt. - #683 unvollständige Übersetzung: input-skaliertes maxTokens + Completeness- Guard (finishReason/Ratio → Retry → status failed statt Silent-Publish).
#733 Image-Jobs → BullMQ (live, Worker→App)
Image-Generierung als echter BullMQ-Job (image-jobs-Queue + Worker-Consumer, conc. 2) statt fire-and-forget im Web-Prozess. Idempotenz (decideImageJobStart, kein Doppel-Charge), Reaper (5min-Tick, kind-scoped, 15min) gegen verwaiste running-Rows. Deploy-sicher (Job überlebt in Redis).
Wave-3-Batch (4 parallele Agenten, gebündelt deployed, 4cd341f)
- #751 Translate-Speed: seo∥quality parallel + seo-Modell gpt-5-mini→ claude-haiku-4-5 (non-reasoning) + Config-Flags TSQS_BACK_TRANSLATE/CROSS_EXAM (default on) → kritischer Pfad 5→~4 Latenzen; off collapsed TSQS 3→1.
- #757 pages-Status: fetchPostStatuses liest posts UND pages → publizierte Seiten nicht mehr fälschlich als „aus WP gelöscht".
- #758 Chat-Timeouts: 45s + 504 auf voice-chat/sources-chat/seo-chat/ prompt-chat (Web-Search-Chats bei 180s).
- #652 Tracing: rewrite + onboarding-v2 tracen mit tenantId; Prompt-Caching + Modell-Drift geprüft = kein Change nötig.
Erkenntnisse / offen
- error-watcher existiert bereits (
src/worker/errorWatcher.ts, alle 6h): scannt audit_log-Cluster, filed GitHub-Issues + Digest-Mail — gated aufGITHUB_TOKEN+GITHUB_REPOim Worker-Env. Deckt den Wunsch „Error-Logs regelmäßig → Issues" ab; nur die zwei Env-Vars fehlen ggf. - Social-Prod-Embed (#755): Runbook + fertige Traefik-Prod-Route hinterlegt;
gated auf embedded Prod-App-Klon (Prod-Secrets). Option A verworfen (bräuchte
CP-Auth-Cookie auf
.calluna.ai).
2026-08-31
Deployed auf Prod (content-pipe.calluna.ai)
- EU-KI-Kennzeichnung für Bilder (Mediathek). Offizielle EU-Icons
(None/AI/AI Generated/AI Modified) werden per
sharpnativ ins Bild komponiert (unten rechts, Auto-Kontrast). Original bleibt erhalten (images.ai_label, reversibel), gerendert wird beim Ausliefern (/raw, Redis-Cache pro Label) und beim WP-Upload (fetchBytes). Migration 0063. Doku: sieheCLAUDE.md→ Stack → Bilder. - Library-Ladezeit-Fix.
loadTaxonomycachte fehlgeschlagene WP-Taxonomy- Abrufe nie → jeder Library-Load lief bis 8s in den WP-Timeout. Jetzt 90s- Negativ-Cache (Backoff) + Timeout 8s→5s. - Beitragsbild-Save-Fix.
featuredImageUrlperz.string().url()lehnte die relative Pipe-Form (/api/images/<id>/raw) ab → „Fehler beim Speichern". Validierung akzeptiert jetzt absolute URL | data:image | /api/images//raw. - Versionierungs-Überarbeitung (Migration 0064):
article_versions.snapshot jsonb= VOLLER Zustand (title/body/metadata inkl. WP-Identität+SEO+OG, status, ccqsBreakdown). Rollback stellt jetzt ALLES her.- Kanonischer Writer
src/lib/articles/versioning.tsersetzt die 4 kopierten Insert-Implementierungen; Cap 10→100. - Coverage-Lücken geschlossen: WP-Sync sichert lokale Fassung VOR Overwrite, Soft-Delete + Pipeline-Baseline (v1) + Hero-Image-Worker versionieren jetzt.
- UI: lesbares Label + Actor (Nutzer/KI/Pipeline), Diff = Version gegen
VORGÄNGER statt gegen aktuellste. Audit:
docs/audit-artikel-versionierung.md.
- SEO-Titel-Konflikt-Fix. Client baselte die Concurrency-Prüfung auf der
eigenen Wall-Clock → bei Clock-Skew falscher „jemand anderes hat geändert".
PATCH gibt jetzt den echten
updatedAtzurück, Client nutzt ihn. - Radar-Quelle-Löschen-Fix. DELETE prunte nur
documents, nieworkspace_settings.data.radarSources→ noch-nicht-gecrawlte Feeds unlöschbar. - Azure-SAS-Bilder-Fix. Alte DALL·E-URLs (24h-SAS) verfielen. Guard lädt
temporäre http-Provider-URLs sofort als permanente data:-URL;
/raw-Proxy redirectet nicht mehr auf tote Upstream-URLs (sauberer 404). Backfill der Alt-Rows offen → #746. - SSRF-Fix (Sicherheit).
ensureFeaturedImagenutzte rohesfetchauf die tenant-kontrollierte siteUrl und schickte das WP-App-Passwort ungeschützt → SSRF + Credential-Exfil. JetztsafeFetch(IP-Pin, DNS-Rebinding-Schutz). - #732 IP-Range-Fix.
isPrivateIPv4blockte viaa===192 && b===0das ganze 192.0.0.0/16 statt nur der reservierten /24 → öffentliche Ranges (Automattic 192.0.78.x) fälschlich als privat → Sitemaps nicht hinzufügbar. - Publish-Credential-orderBy-Fix. Publish griff per bare
.limit(1)evtl. eine token-/username-lose Alt-Row → 401 gegen Front-Door-Sites. Gleiche Ordnung wieloadWordPressCreds. - Translate SEO-Suggest-Guard. Keyword-Kandidaten ohne generierten Übersetzungstext → klarer 409 statt verschwendetem LLM-Call + irreführender „Keine Kandidaten"-Meldung.
Multi-Agenten-Audit (7 Agenten)
Security / Secrets / IDOR / Session-Guards = clean. Worker / WP / Pipeline / DB / API = ~20 Findings → als Issues erfasst.
GitHub-Issues angelegt
- Critical: #733 (Image-Jobs fire-and-forget, Deploy-Verlust), #734 (Translate-Retry-Doppelkosten).
- High: #735 (Publish-TX/Pool-Exhaustion), #736 (Insight/Trends ohne Entitlement-Gate), #737 (Editor speichert kein contentMd — Root-Cause #665/#730), #738 (GRANT-Coverage content_pipe_rt), #739 (CCQS-Scorer auf Deutsch inert).
- Med-High: #740 (Web-Search-Budget), #741 (Cast-Guards 22P02).
- Medium (gebündelt): #743.
- Gemeldete Bugs: #744 (GSC-Liste), #745 (yogamitlara-Kategorien), #746 (Azure-Backfill), #747 (Trends-Duplikate), #748 (stadtlandmama „eingeladen").
- Features/Perf: #742 (Feed-Auto-Discovery), #749 (Wasserzeichen für WP-Bilder), #750 (Translate-Taxonomie-Anzeige), #751 (Translate-Speedup).
- Geschlossen: #732 (IP-Range, live). Kommentiert: #665, #730 → #737.