Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 79 additions & 20 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,40 @@ Changelog ist die Upgrade-Anleitung für die Tools.

## [Unreleased]

### basicbar-auth (→ wird `auth/v0.2.0`)
### basicbar-integrations (→ wird `integrations/v0.3.0`)

**`CapabilitiesView` entfernt** (Framework-Review: kein Tool hat
`GET /api/capabilities/` je aufgerufen — alle vier mischen die Flags in ihr
`whoami`). An seine Stelle tritt `capabilities.capabilities_payload()` mit
genau den drei Schlüsseln, die die Tools heute von Hand zusammensetzen
(`ai_enabled`, `content_default_language`, `content_translation_enabled`).
`basicbar_integrations.urls` enthält nur noch `translate/`.

Migration: Version heben. Wer `basicbar_integrations.urls` einbindet,
verliert den unbenutzten Endpunkt — sonst nichts. Empfohlen: in
`accounts/views.py` `whoami` als
`{**whoami_payload(request), **capabilities_payload(), …}` schreiben und die
drei Inline-Flags löschen.

### Alle Django-Pakete (→ werden `auth/v0.2.1`, `lti/v0.1.5`, `integrations/v0.3.0`)

`__version__` kommt aus den Paket-Metadaten (`importlib.metadata`) statt aus
einem zweiten handgepflegten String — die Versionen drifteten im Review
auseinander. Ein nicht installierter Checkout meldet `0.0.0.dev0`. Keine
Migration.

### Repo

- CHANGELOG: alle Releases seit Juli standen unter „[Unreleased] (→ wird …)“,
obwohl längst getaggt — jetzt je ein datierter Abschnitt pro Tag.
- README: die Paket-Tabelle nennt keine Versionsnummern mehr (sie waren vom
Juli); aktuelle Stände stehen in den Tags und hier.
- Doku-Drift zum Capabilities-Endpunkt in CLAUDE.md und EXTRAKTIONSPLAN
bereinigt.

## auth/v0.2.0 — 2026-10-01

### basicbar-auth

**Session-Endpunkte und Routen im Paket** (Framework-Review; die vier Tools
trugen identische Kopien): `basicbar_auth.views` mit `whoami_payload` /
Expand Down Expand Up @@ -55,7 +88,9 @@ Fallback.
Gruppen-Verlust *jede* Admin-Rolle entzieht, muss lokale Beförderungen
jetzt selbst zurücknehmen (Nutzerverwaltung / Django-Admin).

### @basicbar/ui (→ wird `ui/v0.7.0`)
## ui/v0.7.0 — 2026-10-01

### @basicbar/ui

**TipTap raus aus den Bundles, die keinen Editor rendern** (Framework-Review):
`RichTextEditor` liegt jetzt in einem eigenen Entry
Expand Down Expand Up @@ -110,15 +145,19 @@ Außerdem:
Provider ersetzen.
4. Katalog: keine neuen Keys.

### basicbar-lti (→ wird `lti/v0.1.4`)
## lti/v0.1.4 — 2026-10-01

### basicbar-lti

**Sicherheit: Reflected XSS im LTI-Login behoben.** Die 400er-Antworten von
`lti_login` spiegelten `iss`/`client_id` aus GET-Parametern in eine
HTML-Antwort (Django-Default-Content-Type) — eine präparierte URL konnte so
Skript auf der Tool-Origin ausführen. Alle Fehlerantworten des Endpunkts sind
jetzt `text/plain`. Migration: Version heben, sonst nichts.

### basicbar-auth (→ wird `auth/v0.1.1`)
## auth/v0.1.1 — 2026-10-01

### basicbar-auth

**Sicherheit: Back-Channel-Logout-Tokens werden auf Frische geprüft.** Bisher
prüfte der Endpunkt nur Signatur, Nonce-Verbot und iss/aud/events/sub — ein
Expand All @@ -128,7 +167,9 @@ Logout als DoS). Jetzt ist `iat` Pflicht und darf höchstens
`exp` wird respektiert. Migration: Version heben; bei stark abweichenden
Uhren zwischen IdP und Tool ggf. `OIDC_BACKCHANNEL_MAX_AGE` erhöhen.

### basicbar-integrations (→ wird `integrations/v0.2.2`)
## integrations/v0.2.2 — 2026-10-01

### basicbar-integrations

- `ai.chat_json` und `translation_service.translate` fangen jetzt alle
Transportfehler (`ConnectionResetError`, `IncompleteRead`, …) als
Expand All @@ -140,7 +181,9 @@ Uhren zwischen IdP und Tool ggf. `OIDC_BACKCHANNEL_MAX_AGE` erhöhen.
- Migration: Version heben; wer `str(exc)` an Nutzer durchreicht, zeigt jetzt
aussagekräftigere Texte.

### Template
## Template — 2026-10-01

### Template (basicbar#13, #14, #17)

- **Pins:** basicbar-auth `auth/v0.2.0`, @basicbar/ui `ui/v0.7.0`.
- `config/urls.py` nutzt `include("basicbar_auth.urls")` (OIDC-Routen inkl.
Expand Down Expand Up @@ -186,7 +229,9 @@ Uhren zwischen IdP und Tool ggf. `OIDC_BACKCHANNEL_MAX_AGE` erhöhen.
Konflikte sind in Gerüst-Dateien (compose, Dockerfiles, settings, api.ts)
zu erwarten — Diff lesen; die Identitätsdateien bleiben unberührt.

### @basicbar/ui (→ wird `ui/v0.6.0`)
## ui/v0.6.0 — 2026-10-01

### @basicbar/ui

**Geteilte Einstellungs-Bausteine** (ausleihbar#35): `LanguageOptions`,
`AppearanceControl` und `PreferencesMenu`. Die ersten beiden sind Menüzeilen
Expand All @@ -203,7 +248,9 @@ Migration: additiv, nichts zu tun. Die Tools ergänzen in ihren Katalogen den
Schlüssel „Preferences“ (die übrigen — Appearance, Auto, „(follows your
system)“, Light, Dark, Language — existieren meist schon).

### @basicbar/ui (→ wird `ui/v0.5.1`)
## ui/v0.5.1 — 2026-09-30

### @basicbar/ui

**CSP-tauglicher `RichTextEditor`** (basicbar#9): TipTap hängte beim Mounten
ein `<style data-tiptap-style>` mit den ProseMirror-Grundregeln an `<head>` —
Expand All @@ -219,7 +266,9 @@ Migration: keine, solange das Tool `@basicbar/ui/base.css` importiert (wie
im README beschrieben). Wer `base.css` nicht einbindet, muss die
ProseMirror-Regeln selbst bereitstellen.

### basicbar-integrations (→ wird `integrations/v0.2.1`)
## integrations/v0.2.1 — 2026-09-29

### basicbar-integrations

**Sicherheitsfix:** `clean_media_url` prüfte den rohen String, sodass
Pfade wie `/media/%2e%2e/api/whoami/` oder `/media/a\..\b` durchkamen —
Expand All @@ -242,7 +291,9 @@ konnte — über 300 Zeichen wird jetzt komplett abgelehnt statt gekürzt.
Migration: keine — reiner Bugfix, die öffentliche Signatur von
`clean_media_url`/`clean_html` ändert sich nicht.

### @basicbar/ui (→ wird `ui/v0.5.0`)
## ui/v0.5.0 — 2026-09-29

### @basicbar/ui

**Alt-Text für Bilder in `RichTextEditor`** (basicbar#7, WCAG 1.1.1): direkt
nach einem erfolgreichen Bild-Upload fragt der Editor per `window.prompt`
Expand All @@ -268,7 +319,9 @@ Migration: keine für Tools ohne `onUploadImage` — additiv. Tools mit
Bild-Upload ergänzen die neuen Übersetzungs-Keys
`"Image description (alt text)"` und `"Image description"`.

### @basicbar/ui (→ wird `ui/v0.4.0`)
## ui/v0.4.0 — 2026-09-27

### @basicbar/ui

**`RichTextEditor` + `RichText`** (modulierbar#5), aus AbstimmBAR verschoben:
der eine WYSIWYG-Editor (TipTap) für formatierte Langtext-Felder — Fett,
Expand Down Expand Up @@ -316,7 +369,9 @@ ergänzt die Übersetzungs-Keys `"Bold"`, `"Italic"`, `"Heading (large)"`,
`"Heading (small)"`, `"Bulleted list"`, `"Numbered list"`, `"Link"`,
`"Enter URL"`, `"Insert image (or drag and drop)"`, `"Image upload failed"`.

### @basicbar/ui (→ wird `ui/v0.3.1`)
## ui/v0.3.1 — 2026-08-28

### @basicbar/ui

**Globaler Sprach-Umschalter** (modulierbar#99): Der schwebende
Übersetzungs-Block zeigt jetzt einen kompakten DE/EN-Umschalter, der mit
Expand All @@ -331,15 +386,9 @@ Migration: keine — rein additiv. Neue UI-Strings `"Show all fields in one
language"` und `"Show all fields in {{language}}"` (Tools ergänzen ihre
Übersetzungen).

### basicbar-lti (`lti/v0.1.3`, 2026-08-04 — Eintrag nachgetragen)

- `lti_login` antwortet bei fehlenden Parametern (`iss`, `login_hint`,
`target_link_uri`) und nicht auflösbarer Plattform-Registrierung
(Issuer/Client-ID-Mismatch, auch Trailing-Slash) mit erklärendem `400`
statt opakem `500`; pylti1p3-Exceptions werden abgefangen. Migration:
Version heben, sonst nichts.
## integrations/v0.2.0 + ui/v0.3.0 — 2026-07-23

### basicbar-integrations (→ wird `integrations/v0.2.0`) und @basicbar/ui (→ wird `ui/v0.3.0`)
### basicbar-integrations und @basicbar/ui

**Veraltete Übersetzungen markieren** (modulierbar#31, generisch für alle
Tools): Wird eine Sprache nach der Übersetzung geändert, gilt die
Expand Down Expand Up @@ -376,6 +425,16 @@ Migration (Adoption ist opt-in — ohne neue Props/Aufrufe ändert sich nichts):
`translation may be outdated`, `The other language was changed since
this translation.`, `Mark as up to date`.

## lti/v0.1.3 — 2026-07-20

### basicbar-lti (Eintrag nachgetragen am 2026-08-04)

- `lti_login` antwortet bei fehlenden Parametern (`iss`, `login_hint`,
`target_link_uri`) und nicht auflösbarer Plattform-Registrierung
(Issuer/Client-ID-Mismatch, auch Trailing-Slash) mit erklärendem `400`
statt opakem `500`; pylti1p3-Exceptions werden abgefangen. Migration:
Version heben, sonst nichts.

## lti/v0.1.2 — 2026-07-19

### basicbar-lti
Expand Down
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ GitHub-Actions-Runner öffentlicher „-bar“-Tools die Pakete erreichen könne
## Layout

- `packages/django/basicbar-integrations` — LibreTranslate-/LiteLLM-Clients,
Translate- und Capabilities-Endpoint, HTML-Allowlist (nh3).
Translate-Endpoint, `capabilities_payload()` fürs `whoami` der Tools,
HTML-Allowlist (nh3), Übersetzungs-Sync-Helfer.
- `packages/django/basicbar-auth` — OIDC (mozilla-django-oidc): Backend,
Silent Login, Back-Channel-Logout (mit Session-Index `UserSession`, eigene
Migration), Discovery, `AbstractBasicUser`, Session-Endpunkte
Expand Down
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ Compose · Caddy. Lizenz Apache-2.0.

## Die Pakete

| Paket | Inhalt | Aktuelles Release |
|---|---|---|
| `basicbar-auth` | OIDC-Login (mozilla-django-oidc): Backend mit Claim-Mapping und IdP-Gruppen→Admin, Silent SSO, Back-Channel-Logout, Endpoint-Discovery, `AbstractBasicUser`, optionale Account-Obergrenze und Subject-Drift-Heilung. Betreiber-Hinweise zu Löschfristen/Kennungs-Vakanz im Paket-README. | `auth/v0.1.0` |
| `basicbar-integrations` | Optionale Dienste, aus per Default: LibreTranslate-Client + Übersetzungs-Endpunkt, LiteLLM-Client (OpenAI-kompatibel), Capabilities-Endpoint fürs Frontend, HTML-Allowlist (nh3). | `integrations/v0.1.0` |
| `basicbar-lti` | LTI-1.3-Fundament (PyLTI1p3): Plattform-Registrierung + Staff-API, Tool-Keypair, OIDC-Initiation/JWKS, JIT-Nutzer-Provisionierung mit optionaler E-Mail-Unifizierung, iframe-Middleware. Der Launch selbst bleibt Tool-Code (Kurskontext → Fachmodell). | `lti/v0.1.2` |
| `@basicbar/ui` | Designsystem-Basis: Tailwind-Preset (Font, Dark Mode, Motion — die Farb-Ramps bleiben als Identität im Tool: „ein System, pro Tool ein Akzent“), `base.css` (A11y-Grundausstattung), ThemeProvider, i18n-Bootstrap, `contentLang`, `TranslatableField`/„alle Felder übersetzen“. | `ui/v0.2.1` |

Details und Begründungen: [docs/ADR/](docs/ADR/) · Historie und Vorgehen:
| Paket | Inhalt |
|---|---|
| `basicbar-auth` | OIDC-Login (mozilla-django-oidc): Backend mit Claim-Mapping und IdP-Gruppen→Admin, Silent SSO, Back-Channel-Logout, Endpoint-Discovery, `AbstractBasicUser`, optionale Account-Obergrenze und Subject-Drift-Heilung. Session-Endpunkte (`whoami_payload`, `logout_view`, `set_language`) und URL-Verdrahtung. Betreiber-Hinweise zu Löschfristen/Kennungs-Vakanz im Paket-README. |
| `basicbar-integrations` | Optionale Dienste, aus per Default: LibreTranslate-Client + Übersetzungs-Endpunkt, LiteLLM-Client (OpenAI-kompatibel), `capabilities_payload()` fürs `whoami`, HTML-Allowlist (nh3), Übersetzungs-Sync-Helfer. |
| `basicbar-lti` | LTI-1.3-Fundament (PyLTI1p3): Plattform-Registrierung + Staff-API, Tool-Keypair, OIDC-Initiation/JWKS, JIT-Nutzer-Provisionierung mit optionaler E-Mail-Unifizierung, iframe-Middleware. Der Launch selbst bleibt Tool-Code (Kurskontext → Fachmodell). |
| `@basicbar/ui` | Designsystem-Basis: Tailwind-Preset (Font, Dark Mode, Motion — die Farb-Ramps bleiben als Identität im Tool: „ein System, pro Tool ein Akzent“), `base.css` (A11y-Grundausstattung), ThemeProvider, i18n-Bootstrap, `contentLang`, `TranslatableField`/„alle Felder übersetzen“, Preferences-Menü, `RichText`; `RichTextEditor` (TipTap) als eigener Entry. |

Aktuelle Versionen: die Tags `<paket>/vX.Y.Z` bzw. [CHANGELOG.md](CHANGELOG.md)
(dort auch die Migrationsschritte je Release). Details und Begründungen:
[docs/ADR/](docs/ADR/) · Historie und Vorgehen:
[docs/EXTRAKTIONSPLAN.md](docs/EXTRAKTIONSPLAN.md).

## Neues Tool erzeugen
Expand Down
17 changes: 11 additions & 6 deletions docs/EXTRAKTIONSPLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ basicbar/
│ │ ├── basicbar-auth/ # OIDC-Backend, Discovery, Session-Endpoints,
│ │ │ # AbstractBasicUser (abstrakt!), Permissions-Basis
│ │ ├── basicbar-integrations/ # translation_service (LibreTranslate),
│ │ │ # ai (LiteLLM), Capabilities-Endpoint
│ │ │ # ai (LiteLLM), capabilities_payload
│ │ └── basicbar-lti/ # LTI-1.3-App aus abstimmbar (pyLTI1p3-Muster)
│ └── ui/ # @basicbar/ui (npm): Design-Tokens (CSS-Variablen),
│ # Theme + Dark Mode, i18n-Setup, contentLang,
Expand Down Expand Up @@ -76,9 +76,13 @@ Upgrades pro Tool.
`accounts.User(AbstractBasicUser)` mit eigenen Migrationen. Bestehende Tools
müssen ihr User-Model dafür *nicht* umbauen — sie adoptieren zunächst nur
Backend/Discovery/Views.
2. **Capabilities-Endpoint** in `basicbar-integrations`: `GET /api/capabilities`
→ `{ translation: bool, ai: bool, lti: bool }`. Frontend blendet Features
automatisch ein/aus; keine Build-Varianten.
2. **Feature-Flags im `whoami`**, nicht als eigener Endpunkt: die Tools
mischen `basicbar_integrations.capabilities.capabilities_payload()`
(`ai_enabled`, `content_default_language`, `content_translation_enabled`)
in ihr `/api/whoami/` — ein Request beim Laden, das Frontend blendet
Features automatisch ein/aus; keine Build-Varianten. (Der ursprünglich
geplante `GET /api/capabilities` wurde von keinem Tool genutzt und ist mit
integrations 0.3.0 wieder entfernt.)
3. **Optionalität per Env**, wie bereits etabliert (`LIBRETRANSLATE_URL`,
`AI_PROVIDER`/`AI_BASE_URL`/…): aus = Feature unsichtbar. Stdlib-`urllib`-
Ansatz (keine Zusatzabhängigkeiten) beibehalten.
Expand Down Expand Up @@ -190,8 +194,9 @@ Distribution: Repo öffentlich, Installation als GitLab-Archiv-Tarball vom
Tag (kein git im Image, Dockerfiles unverändert). Umstellungs-MRs:
ausleihbar !166, abstimmbar !90 — beide Suiten grün, Docker-Builds
end-to-end verifiziert. Der Sync-Workflow (taggen → pinnen → bumpen) ist
damit einmal komplett bewiesen. Capabilities-Endpoint ist im Paket, die
Frontend-Adoption in den Tools folgt bei Gelegenheit (z. B. mit Phase 3).
damit einmal komplett bewiesen. (Der Capabilities-Endpoint wurde nie
adoptiert und ist mit integrations 0.3.0 durch `capabilities_payload()`
ersetzt — siehe Entscheidung 2.)

### Phase 3 — `@basicbar/ui` (der Design-Sync, Hauptmotivation)

Expand Down
9 changes: 8 additions & 1 deletion packages/django/basicbar-auth/basicbar_auth/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2026 Universität Osnabrück (virtUOS)

__version__ = "0.2.0"
from importlib.metadata import PackageNotFoundError, version

# Single source of truth is pyproject.toml; an uninstalled checkout (e.g. the
# package tests run straight from the tree) reports a dev marker instead.
try:
__version__ = version("basicbar-auth")
except PackageNotFoundError: # pragma: no cover
__version__ = "0.0.0.dev0"
2 changes: 1 addition & 1 deletion packages/django/basicbar-auth/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "basicbar-auth"
version = "0.2.0"
version = "0.2.1"
description = "OIDC-Fundament der virtUOS -bar-Tools: Backend, Silent Login, Back-Channel-Logout, Discovery, AbstractBasicUser, optionale Account-Limits"
readme = "README.md"
requires-python = ">=3.12"
Expand Down
18 changes: 14 additions & 4 deletions packages/django/basicbar-integrations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ Provider-SDKs.
`{translated}`; validiert Sprachen gegen `settings.LANGUAGES`, sanitized
HTML-Ergebnisse serverseitig. Permission per Subclass anpassbar
(Default `IsAuthenticated`).
- `views.CapabilitiesView` — `GET` → `{"translation": bool, "ai": bool, …}`,
damit das Frontend Features ohne Build-Varianten ein-/ausblendet;
erweiterbar über `extra_capabilities()`.
- `capabilities.capabilities_payload()` — `{"ai_enabled", "content_default_language",
"content_translation_enabled"}` für das `whoami` des Tools (neben
`basicbar_auth.views.whoami_payload`), damit das Frontend Features ohne
zweiten Request und ohne Build-Varianten ein-/ausblendet.
- `translation_sync` — Helfer für den Übersetzungs-Sync-Zustand pro Feld
(`record_synced`, `stale_map`, `modeltranslation_values`, …).
- `html_sanitize` — die eine HTML-Allowlist für Rich-Content (nh3-basiert).

## Einbinden
Expand All @@ -24,7 +27,14 @@ Provider-SDKs.
INSTALLED_APPS = [..., "basicbar_integrations"]

# urls.py
path("api/", include("basicbar_integrations.urls")), # translate/ + capabilities/
path("api/", include("basicbar_integrations.urls")), # translate/

# accounts/views.py
from basicbar_auth.views import whoami_payload
from basicbar_integrations.capabilities import capabilities_payload

def whoami(request):
return JsonResponse({**whoami_payload(request), **capabilities_payload()})
```

Alle Settings haben Defaults („aus“) — ein Tool ohne Konfiguration startet
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2026 Universität Osnabrück (virtUOS)

__version__ = "0.2.2"
from importlib.metadata import PackageNotFoundError, version

# Single source of truth is pyproject.toml; an uninstalled checkout (e.g. the
# package tests run straight from the tree) reports a dev marker instead.
try:
__version__ = version("basicbar-integrations")
except PackageNotFoundError: # pragma: no cover
__version__ = "0.0.0.dev0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2026 Universität Osnabrück (virtUOS)

"""The feature flags a tool's SPA needs at load time.

Every -bar tool mixes the same three keys into its ``/api/whoami/`` payload
(next to ``basicbar_auth.views.whoami_payload``) so the SPA can show or hide
optional features without a second round-trip or build variants::

return JsonResponse({**whoami_payload(request), **capabilities_payload()})

This replaces the former ``CapabilitiesView`` (``GET /api/capabilities/``),
which no tool ever called — one request at startup is enough.
"""
from django.conf import settings

from . import ai, translation_service


def capabilities_payload() -> dict:
return {
# AI-assisted features (LiteLLM proxy) may be offered.
"ai_enabled": ai.is_enabled(),
# Canonical authoring language of this deployment (modeltranslation's
# default), and whether machine-translation drafts are available.
"content_default_language": getattr(
settings, "MODELTRANSLATION_DEFAULT_LANGUAGE", settings.LANGUAGE_CODE
),
"content_translation_enabled": translation_service.is_enabled(),
}
Loading
Loading