Skip to content

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:

  1. Welche Version läuft wo (Tenant-Matrix für Container, package.json für npm-Deps).
  2. Welche Versionen gibt es (alle Releases seit unserer aktuellen, chronologisch).
  3. Was bringen die neuen Versionen (Changelog-Sections strukturiert: Features, Bugfixes, Deprecations, Upgrade-Notes).
  4. Was davon betrifft Prilog konkret (Cross-Check mit unserem API-Endpoint-Inventar).
  5. Wie haben wir uns entschieden (Annotation pro Release: relevant/in-use/geplant/ignoriert + freier Notiz-Text).

Was getrackt wird (initial)

KomponenteQuelleIdentifierWarum kritisch
SynapseGitHub-Releaseselement-hq/synapseMatrix-Kern, viele Admin-API-Aufrufe in Backend
MinIOGitHub-Releasesminio/minioPer-Tenant-S3-Storage
n8nGitHub-Releasesn8n-io/n8nWorkflow-Automation für weser, ggf. weitere
PostgresDockerHub-Tagspostgres (Tag-Filter: \d+-alpine)DB für jeden Tenant
faster-whisperGitHub-ReleasesSYSTRAN/faster-whisperVoice-Transkription (Flurfunk)
matrix-js-sdkNPM-Registrymatrix-js-sdkWeb-Client-Chat-SDK
@fastify/*NPM-Registryje packageBackend-Foundation
prismaNPM-RegistryprismaDB-Layer
tiptapNPM-Registry@tiptap/coreDMS-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_at

Drei Adapter (alle hinter einer Schnittstelle)

typescript
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:

typescript
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)

KomponenteQuelle für laufende Version
Synapsetenant_box_manifests (pro Tenant) bzw. tenant_box_specs.components[name=synapse].image
MinIOdito
Postgresdito
n8nhat (noch) keine Spec-Eintragung — für weser direkt aus docker-compose lesen
matrix-js-sdkprilog-web-client/package.json
Backend-Depsprilog-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/**/*.ts nach Pattern /_matrix/ und /_synapse/admin/
  • prilog-web-client/src/**/*.ts(x) nach Pattern /_matrix/ und matrix-js-sdk-Imports/-Methoden
  • prilog-matrix-connector/src/**/*.py nach Synapse-Module-API-Imports

Schreibt in component_api_usage. Wöchentlich via Cron.

Cross-Check-Logik: Bei jedem neuen Release:

  1. Parse body_structured.deprecations und body_structured.upgradeNotes nach Endpoint-Pattern (/_matrix/..., /_synapse/admin/...).
  2. Match gegen component_api_usage.endpoint.
  3. 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

JobScheduleWas
component-release-fetch0 6 * * * (täglich 06:00 UTC)Alle enabled definitions polled (ETag falls möglich)
component-api-usage-crawl0 7 * * 1 (Mo 07:00)Re-Crawl der Repos
component-alert-recompute0 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)

  1. Schema-Migration (Tabellen + Indizes)
  2. Component-Definitions seeden (initial 6-8 Komponenten)
  3. GitHub-Adapter + Changelog-Parser (zuerst — deckt 80% ab)
  4. DockerHub-Adapter + NPM-Adapter (für Postgres + matrix-js-sdk)
  5. API-Usage-Crawler-Script (in scripts/, manuell ausführbar)
  6. Backend-Routes (Liste, Detail, Annotation, Recompute-Alerts)
  7. Admin-Frontend-Page (Liste + Detail mit Annotation)
  8. Cron-Jobs einhängen
  9. Erste Run-Durchgänge (fetch + crawl, Daten anschauen)
  10. 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.