kirche-einfach/CHANGELOG.md

9.4 KiB

Changelog

All notable changes to this project will be documented in this file. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Changed

  • Declutter: shared BaseApiClient (LFX/Langflow) with tenacity transport retry, single get_db, model_validate mappers, unified LFX/Langflow error mapping, stream logic moved to runner.py, sync_full_pass single orchestration (API+CLI), shared model base (utcnow/ts_column), unified auth counters, httpx in deploy_flow.py, atomicwrites file writes, secure-package headers.
  • Auth: stateless JWT sessions (HS256, 30d, HttpOnly cookie unchanged) replace the user_sessions table (Alembic revision drops it; all sessions invalidated at deploy); slowapi run throttle replaces the hand-rolled sliding window; mail via jinja template + fastapi-mail (same copy/fallback contract); CLIs on typer; JWT_SECRET enforced by check_prod.py.
  • Forms: thin variant components over shared components/kirche/_form_core.py (codegen-inlined by kirche_node() for LFX; all 5 flows regenerated + level-4 validated), structured visible_if key alongside legacy markers, LangflowClient.upsert_flow + scripts/push_flows_to_langflow.py (6 canonical flows pushed to Langflow UI).
  • Store/sync: single next_version_no query per version, validation only at the create_version choke point, mtime-cached .flowsignore.
  • Fix batch: typer CLIs exit non-zero via typer.Exit (check_prod gate works again); JWT expiry 30d→7d with startup warning and new expiry/deleted-user tests; deleted dead resolve_tenant, test alias helpers now delegate to conftest (flows/approvals/sync/deploy suites migrated to shared fixtures); AdminTab reads via react-query; Mantine aligned to 9.6.3 (consistent lockfile, npm ci green).
  • Tests (full real LFX kept): shared conftest helpers + tests/_harness.py adopted by fixtures and smoke script, parametrized matrices (export stems, check_prod env, deploy failures, sync listing failures, API auth probes, input_schema types), relaxed brittle asserts (ui:order sets, per-flag cookie asserts, SSE any-match).
  • Frontend: react-query reads + notifications, useForm+zod static forms, shared DecisionButtons/ErrorAlert/JsonView/FormattedDate/RunsTable/Landing blocks, new aggregate GET /api/runs kills the Tasks N+1, Promise.all version fetches, sharp icons, selector-based screenshots, dead photo removed.

Added

  • Aggregate GET /api/runs (tenant-scoped runs with flow names, single query).
  • Branched questionnaires: [visible_if feld=Wert] markers in a CustomInputForm field's info (code editor) show the field only when the condition holds — nested to any depth, with & for AND conditions and quotes for values with spaces. The parser emits allOf/if/then branches (branch-scoped required, template-order placement); unknown triggers, cycles, and unsupported trigger types fail open (always visible). New demo flow bauvorhaben.json (4 levels + sibling branch + bool trigger). Values of hidden fields are kept and submitted.
  • Run envelope carries the asked field names (fields, from the version's form schema): collect() emits defaults only for asked AND currently visible fields (hidden branch fields stay out, like the frontend never submits them), so templates may declare fields unknown to the component code and unasked code defaults stay out of the run output. Without the list (raw dicts, Langflow playground) all visible declared defaults apply.
  • Standalone CustomInputBauvorhaben component ("Bauvorhaben Form" in the kirche palette, zero shared code with CustomInputForm — the LFX runtime executes embedded module source without our package); the bauvorhaben flow uses it, and Langflow no longer normalizes the node back to the default form on import.
  • Form parser also recognizes user-built CustomComponent nodes whose display name ends with "Form" (e.g. Mitarbeiter Einstellen Form) — same template contract, no kirche base needed.
  • Standalone CustomInputMitarbeiter component ("Mitarbeiter Einstellen Form") with hiring flow incl. Gehaltsrechner, rebuilt generator-owned.
  • Admin flow table shows one row per flow (latest version, with live version note when an older version is deployed) instead of one row per version.
  • Step-by-step guide for new workflow modules: docs/new_workflow_module.md (linked from README).

Changed

  • CustomInputForm.collect() is now dynamic and returns Data (JSON) instead of Message: fields can be renamed, added, or removed in the Langflow code editor with no collect() change, and values travel as a real JSON object. The form parser keeps name keys verbatim (empty names skipped, collisions suffixed) and the run envelope merges unknown keys. Note: a terminal ChatOutput renders Data as a fenced ```json block, and downstream components should read .data, not .text.

Added

  • Flow-Sync ist jetzt ein manueller Full-Pass: POST /api/flows/sync (Button "Aus Langflow synchronisieren" in der Verwaltung) holt erst alle Flows aus Langflow nach backend/flows/*.json und deployed sie danach automatisch (Report mit pulled-Liste). Der Hintergrund-Beobachter und der Startup-Sync bleiben dateibasiert. Die Verwaltung zeigt eine deutsche Schritt-Anleitung direkt beim Sync-Button.
  • LLM-Provider-Umgebung für Langflow: OPENAI_API_KEY + OPENAI_BASE_URL in .env (OpenAI-kompatible Endpoints) erzeugen automatisch restart-feste Global Variables in Langflow; LFX liest dieselben Werte.
  • Langflow-Sitzungen halten länger: LANGFLOW_REFRESH_TOKEN_EXPIRE_SECONDS (Default weiter 7 Tage, Dev-Beispiel 90) + stabile JWT-Signatur via LANGFLOW_SECRET_KEY — kein Re-Login nach Container-Restarts.

Fixed

  • Flow-Sync aus Langflow: neue Flows blieben unsichtbar, weil LFX-Uploads mit Permission denied scheiterten (named Volume root-owned, LFX läuft rootless). lfx-entrypoint.sh chownt /flows per gosu vor dem Start; zusätzlich Pull-Dedup (wiederverwendet gleichnamige/identische Dateien statt Bindestrich-Duplikate wie simple-rule.json, die jede Sync-Meldung mit Namenskonflikten füllten).
  • Sync-Dateinamen behalten die Langflow-Namen (test_flow.json statt test-flow.json; nur dateisystem-reservierte Zeichen werden ersetzt).
  • Gezogene Flow-Dateien sind world-readable (0o644): mkstemp erzeugte 0o600-Dateien, die Langflow beim Start abstürzen ließen (Permission denied in /app/flows, Crash-Loop) und der API Fehler (unreadable) verursachten.
  • LANGFLOW_SECRET_KEY muss ein gültiger Fernet-Key sein (44 Zeichen, urlsafe-base64): ein Hex-String brach die Variablen-Verschlüsselung mit Fernet key must be 32 url-safe base64-encoded bytes (500 beim Anlegen von Global Variables — Provider-Keys ließen sich nicht speichern). .env.example dokumentiert die Erzeugung.
  • LFX runtime user gets a home directory (useradd -m, HOME set): without one every flow run failed with "Settings service not found".

Security

  • Production ops: scripts/check_prod.py validates .env secrets and modes before deploy (with tests); README production checklist (proxy gates for Langflow, secret rotation, upgrade runbook).

Security

  • API authorization: flow management is admin-only, runs and run/approval reads require login with strict session-tenant scoping, approval decisions record the session user, and flow callbacks authenticate with a shared X-Callback-Token (CALLBACK_TOKEN). Request-controlled tenant_id, callback_base_url and continuation_flow_id were removed (SSRF / cross-tenant / flow-chaining hardening); continuations now resolve from the admin-authored definition.
  • Frontend: /app/* routes require login; approver is the session user.
  • Edge hardening: interactive API docs only with debug, security headers (nosniff/frame/Referrer-Policy), 2 MiB body cap, per-IP run throttle, generic upstream-error responses, magic links never logged.
  • Containers run rootless (api/vite as uid 1000, lfx as lfx user); frontend fails closed to preview mode unless FRONTEND_MODE=dev.

Added

  • Landing page: status-quo problem block, 5-step process with quote, portal overview with admin areas, AI platform parts, exception tiers, quantified benefits, integrations, use-case examples, pilot-program section, expanded FAQ (8 items incl. KI data usage, price model, responsibility).

Changed

  • Landing page copy overhauled after 3 reviewer rounds (church-admin compliance wording: "entwickelt nach DSG-EKD/DSGVO" + AVV/TOMs, human release responsibility, honest pilot framing instead of invented testimonials; CTA now "Pilotgespräch vereinbaren").
  • New photo pilot-meeting.webp (consultation scene, self-hosted).
  • Backend lint + format standards via ruff (pinned dev dependency, enforced in CI): uv run ruff check ., uv run ruff format.

[0.1.0] - 2026-09-13

Added

  • Repo scaffold: docker-compose dev/prod, version-pinned images, devcontainer.
  • Magic-link auth, access requests, RBAC, frontend access-management UI.
  • File-based flow source of truth + sync engine + LFX runtime.
  • RJSF dynamic forms, router, Mantine dark-mode design system.
  • Conversion landing page, automated screenshots, bell-tower favicon.
  • Email-first login, branded multipart HTML magic-link mails.
  • lfx level-4 validation on all canonical flows + regression test.