Component-Release-Watch — Konzept
Status: Konzept + Implementation in Arbeit ab 2026-05-12 (Nacht-Schicht) Zielgruppe: Plattform-Admins. Schul-Admins sehen das nicht.
Worum es geht
Prilog hängt an einer Handvoll externer Komponenten: Synapse, Postgres, MinIO, n8n, faster-whisper, matrix-js-sdk und einer Reihe NPM-Dependencies. Jede dieser Komponenten veröffentlicht regelmäßig Releases — mit neuen Features, gefixten Bugs, deprecateten APIs.
Bislang: Wenn ein Plattform-Admin nicht zufällig die Release-Notes auf GitHub liest, übersehen wir Features und übersehen wir Breaking-Changes. Beispiel: synapse-leander läuft 1.124.0, synapse-demo 1.151.0 — niemand wusste warum.
Ziel: Eine zentrale Stelle im Admin-Backend, die für jede getrackte Komponente zeigt:
- Welche Version läuft wo (Tenant-Matrix für Container, package.json für npm-Deps).
- Welche Versionen gibt es (alle Releases seit unserer aktuellen, chronologisch).
- Was bringen die neuen Versionen (Changelog-Sections strukturiert: Features, Bugfixes, Deprecations, Upgrade-Notes).
- Was davon betrifft Prilog konkret (Cross-Check mit unserem API-Endpoint-Inventar).
- Wie haben wir uns entschieden (Annotation pro Release: relevant/in-use/geplant/ignoriert + freier Notiz-Text).
Was getrackt wird (initial)
| Komponente | Quelle | Identifier | Warum kritisch |
|---|---|---|---|
| Synapse | GitHub-Releases | element-hq/synapse | Matrix-Kern, viele Admin-API-Aufrufe in Backend |
| MinIO | GitHub-Releases | minio/minio | Per-Tenant-S3-Storage |
| n8n | GitHub-Releases | n8n-io/n8n | Workflow-Automation für weser, ggf. weitere |
| Postgres | DockerHub-Tags | postgres (Tag-Filter: \d+-alpine) | DB für jeden Tenant |
| faster-whisper | GitHub-Releases | SYSTRAN/faster-whisper | Voice-Transkription (Flurfunk) |
| matrix-js-sdk | NPM-Registry | matrix-js-sdk | Web-Client-Chat-SDK |
| @fastify/* | NPM-Registry | je package | Backend-Foundation |
| prisma | NPM-Registry | prisma | DB-Layer |
| tiptap | NPM-Registry | @tiptap/core | DMS-Editor |
Weitere kommen später dazu via Component-Definitions-Tabelle — keine Code-Änderung nötig.
Architektur
Drei Tabellen
component_definitions // Was wird getrackt?
component (PK) // 'synapse', 'minio', 'matrix-js-sdk', ...
display_name
category // 'container' | 'npm' | 'python_lib'
source_type // 'github_release' | 'dockerhub_tag' | 'npm_registry'
source_identifier // repo path / package name
current_version_query // wie wir die aktuell laufende Version ermitteln
// 'spec:component=synapse.image' oder
// 'package_json:prilog-backend-api/prisma' etc.
tag_filter_regex // optional, fuer DockerHub-Tag-Filter
enabled // soft-disable ohne loeschen
notes
created_at, updated_at
component_releases // Release-Cache pro Komponente
id (cuid)
component // FK → component_definitions
version // 'v1.151.0' (wie GitHub es liefert)
version_normalized // '1.151.0' (semver, sortierbar)
is_prerelease
source_url // GitHub-Release-URL bzw. DockerHub-Tag-URL
published_at
fetched_at
body_markdown // Original-Changelog
body_structured // jsonb: { features: [], bugfixes: [], deprecations: [], upgradeNotes: [], internal: [] }
prilog_status // 'new' | 'reviewed' | 'relevant' | 'in_use' | 'planned' | 'ignored'
prilog_notes // Markdown, Plattform-Admin notiert
evaluated_at
evaluated_by // Matrix-UserId
UNIQUE(component, version)
component_api_usage // Wo nutzen wir was im Code?
id
component // FK
endpoint // '/_matrix/client/v3/login' oder npm-Funktion 'createClient'
method // 'POST' | 'GET' | null fuer non-HTTP
category // 'matrix_client_api' | 'synapse_admin_api' | 'npm_export'
file_path // 'src/services/synapse-jwt-login.service.ts'
line_number
repo // 'prilog-backend-api' | 'prilog-web-client' | 'prilog-matrix-connector'
snippet // 1-3 Zeilen Code-Kontext
last_seen_at
UNIQUE(component, endpoint, method, file_path, line_number, repo)
component_release_alerts // berechnet, wenn ein Release ein genutztes Endpoint deprecated
id
release_id (FK)
endpoint
severity // 'deprecated' | 'removed' | 'breaking_change'
message
acknowledged
created_atDrei Adapter (alle hinter einer Schnittstelle)
interface ReleaseFetchAdapter {
fetchReleases(def: ComponentDefinition, since?: string): Promise<RawRelease[]>;
}
// Implementierungen:
// GithubReleaseAdapter — api.github.com/repos/.../releases
// DockerHubTagAdapter — hub.docker.com/v2/repositories/.../tags
// NpmRegistryAdapter — registry.npmjs.org/<pkg>Changelog-Parser
Markdown-Parser für GitHub-Release-Bodies, der gängige Sections in JSON extrahiert:
parseChangelog(markdown: string): {
features: ChangelogEntry[];
bugfixes: ChangelogEntry[];
deprecations: ChangelogEntry[];
upgradeNotes: ChangelogEntry[];
internal: ChangelogEntry[];
raw: string;
}
interface ChangelogEntry {
text: string;
prNumber?: number; // aus "#1234"
prUrl?: string;
}Regex-basiert, robust gegenüber Format-Variationen. Fallback: raw-text bleibt verfügbar.
Versions-Matrix (aktuelle Versionen aus den vorhandenen Quellen)
| Komponente | Quelle für laufende Version |
|---|---|
| Synapse | tenant_box_manifests (pro Tenant) bzw. tenant_box_specs.components[name=synapse].image |
| MinIO | dito |
| Postgres | dito |
| n8n | hat (noch) keine Spec-Eintragung — für weser direkt aus docker-compose lesen |
| matrix-js-sdk | prilog-web-client/package.json |
| Backend-Deps | prilog-backend-api/package.json + package-lock.json |
→ Neuer Service currentVersionResolver(component) führt die Logik aus.
Crawler für API-Usage
Ziel: Wir wollen bei einem Synapse-Release 1.155 automatisch sehen "X deprecated POST /_synapse/admin/v1/reset_password, das nutzen wir in 4 Stellen".
Lösung: Ein Script scripts/crawl-component-usage.ts scannt:
prilog-backend-api/src/**/*.tsnach Pattern/_matrix/und/_synapse/admin/prilog-web-client/src/**/*.ts(x)nach Pattern/_matrix/und matrix-js-sdk-Imports/-Methodenprilog-matrix-connector/src/**/*.pynach Synapse-Module-API-Imports
Schreibt in component_api_usage. Wöchentlich via Cron.
Cross-Check-Logik: Bei jedem neuen Release:
- Parse
body_structured.deprecationsundbody_structured.upgradeNotesnach Endpoint-Pattern (/_matrix/...,/_synapse/admin/...). - Match gegen
component_api_usage.endpoint. - Bei Treffer:
component_release_alerts-Eintrag erstellen, Plattform-Admin notification.
Admin-UI
Page /admin/components
Komponenten-Übersicht
┌────────────────────────────────────────────────────────────────┐
│ Komponente │ Laufend │ Aktuell │ Δ │ Alerts │ │
├────────────────────────────────────────────────────────────────┤
│ Synapse │ 1.124–1.151 │ 1.155.0 │ 4–31 │ 2 ● │ →│
│ MinIO │ RELEASE.… │ RELEASE │ 0 │ 0 │ →│
│ matrix-js-sdk │ 34.5.0 │ 35.1.0 │ 12 │ 0 │ →│
│ ... │ │ │ │ │ │
└────────────────────────────────────────────────────────────────┘Detail-Page /admin/components/synapse
- Tenant-Versions-Matrix oben (4 Tenants × ihre Version)
- Release-Liste (alle Versionen neuer als unsere älteste), mit Filter "unreviewed | relevant | in_use | ignored"
- Klick auf Release → Detail-Panel mit:
- strukturierten Sections (Features als Liste, Bugfixes, Deprecations rot-markiert, Upgrade-Notes hervorgehoben)
- Annotation-Felder (Status + Notes), editierbar
- bei Deprecations: Cross-Match-Anzeige "Prilog nutzt das in X Dateien" mit Direktlinks
Cron-Jobs
| Job | Schedule | Was |
|---|---|---|
component-release-fetch | 0 6 * * * (täglich 06:00 UTC) | Alle enabled definitions polled (ETag falls möglich) |
component-api-usage-crawl | 0 7 * * 1 (Mo 07:00) | Re-Crawl der Repos |
component-alert-recompute | 0 8 * * * (täglich 08:00) | Cross-Match Deprecations × Usage |
Bei neuen Alerts: Sidebar-Badge im Admin.
Was später (Phase 2+)
- LLM-First-Vorschlag — Claude/GPT bekommt Changelog + API-Inventar, schlägt "relevant für Prilog: …" vor, Admin reviewed.
- Auto-Tag aus PR-Titeln — "[Feature]", "[Breaking]", "[Deprecation]" als Tags.
- Trend-Chart — Release-Frequenz, Deprecation-Rate.
- Diff-View — Stelle zwei beliebige Versionen gegenüber.
- Mehr Quellen: GitHub-Advisory-DB (CVEs), Docker-Hub-Sicherheits-Scans.
Phasen-Plan (kompakt)
- Schema-Migration (Tabellen + Indizes)
- Component-Definitions seeden (initial 6-8 Komponenten)
- GitHub-Adapter + Changelog-Parser (zuerst — deckt 80% ab)
- DockerHub-Adapter + NPM-Adapter (für Postgres + matrix-js-sdk)
- API-Usage-Crawler-Script (in scripts/, manuell ausführbar)
- Backend-Routes (Liste, Detail, Annotation, Recompute-Alerts)
- Admin-Frontend-Page (Liste + Detail mit Annotation)
- Cron-Jobs einhängen
- Erste Run-Durchgänge (fetch + crawl, Daten anschauen)
- Docs in docs.prilog.chat
Diese Reihenfolge ist auch die Implementations-Reihenfolge der Nacht-Schicht.
Designentscheidungen
Warum nicht Dependabot/Renovate? Die machen Pull-Requests gegen Repositories — gut für npm-Bumps, aber nicht für Container-Images, nicht für Synapse, und ohne Prilog-spezifische Sicht (welche Endpoints nutzen wir, was bedeutet diese Deprecation für uns konkret).
Warum die Annotation in der DB statt in der Spec? Annotation ist organisch, ändert sich beim Reviewen. Spec ist append-only versioniert. Trennung sauber.
Warum nicht einfach RSS? GitHub bietet RSS-Feeds für Releases, aber ohne strukturierten Body. Wir brauchen das Markdown-Parsing, weil "Features-Liste" und "Deprecations-Liste" maschinen-lesbar sein müssen.
Warum kein separater Service? Wir sind Single-Tenant-Backend für die Plattform-Admin-Sicht — ein Cron-Job + drei Tabellen genügt. Microservice wäre Over-Engineering.
Warum so viele Adapter-Quellen? Weil unterschiedliche Komponenten unterschiedlich publizieren. Synapse hat saubere GitHub-Releases. Postgres hat keine GitHub-Releases im klassischen Sinn — wir nehmen DockerHub-Tags. NPM-Deps sind eh über registry.npmjs.org zugänglich.
Erfolgsmessung
- Wir wissen vor jedem Synapse-Update, ob Endpoints die wir nutzen verschwinden.
- Wir können einer neuen Person zeigen, warum wir Feature X aus Version Y nicht übernommen haben (steht im prilog_notes-Feld).
- Tenant-Versions-Drift ist sichtbar (siehe leander 1.124 vs demo 1.151 heute).
- Update-Entscheidungen sind nachvollziehbar.