kirche-einfach/README.md

6.9 KiB

Kirche Einfach

AI-assisted administration platform for church organizations.

Staff describe a request in plain words. The platform guides them through the process, checks the rules automatically, and asks a human only when something needs judgment. Every step is documented and traceable.

Features

  • Visual flow authoring — design decision flows in Langflow, then bring them into the platform.
  • Flows as files — each flow lives as one JSON file under backend/flows/. The directory is the source of truth: committed to git, reviewable, diffable.
  • Automatic sync — the API watches backend/flows/ and reconciles every change into the database and the runtime: new files become flows, edits become new versions, deleted files remove the flow (including its runs). Same on every startup; also triggerable via POST /api/flows/sync or uv run python scripts/sync_flows.py --sync.
  • Versioned runtime — every change creates an immutable version; versions deploy to the lightweight LFX runtime and can run synchronously or streamed.
  • Approvals — a flow can pause and ask a human for a decision. Approving can automatically start a follow-up ("continuation") flow.
  • Access management — public landing page (German) with an access-request form (request + approval). Approved users get a passwordless magic-link invite by email (SMTP via .env); sessions are HttpOnly cookies, tenants come from the session. First admin via POST /api/auth/admin-bootstrap (only on an empty user table, email must be in ADMIN_EMAILS).
  • Dynamic forms — flows declare form fields as typed inputs on a CustomInput* custom component (reusable library in backend/components/, mounted into Langflow via LANGFLOW_COMPONENTS_PATH). GET /api/flows/{id}/input-schema derives a JSON Schema + RJSF uiSchema from the deployed version; the webapp renders the matching form automatically. Flows without such a node fall back to a single textarea. See backend/components/kirche/README.md for authoring new form fields.
  • Web UI — landing page (Start), access request (Zugang), and the logged-in webapp: Workflows (choose + run with dynamic form), Aufgaben (approvals), Verwaltung (admin: access requests, import, sync, deploy).

Infrastructure

One docker-compose.yml at the repo root runs the whole stack — identical services in dev and prod. Dev-only needs (editor, SSH keys, autoreload, docker CLI) come from .devcontainer/devcontainer.json.

flowchart LR
    subgraph Repo["Git repo — source of truth"]
        FLOWS["backend/flows/*.json<br/>one Langflow export per flow"]
    end
    subgraph Stack["Compose stack (dev + prod)"]
        UI["frontend — React UI (3000)"]
        API["api — FastAPI (8000)<br/>+ embedded flow-watcher"]
        DB[("app.db — SQLite file")]
        LF["langflow — authoring UI (7860)<br/>langflow.db — SQLite file"]
        LFX["lfx — flow runtime (6004)"]
        WT["watchtower — nightly image updates (prod)"]
    end
    UI --> API
    FLOWS -->|watch + sync| API
    API -->|definitions · versions · runs · approvals| DB
    API -->|pull / export| LF
    API -->|upload · run · unregister| LFX
    LFX -->|approval callbacks| API
    WT -.->|updates :latest images| LF
Service Purpose URL
React frontend Web UI (Vite, HMR in dev) http://localhost:3000
FastAPI backend API + flow orchestration (reload in dev) http://localhost:8000
API docs Swagger UI http://localhost:8000/api/docs
Langflow Visual flow authoring http://localhost:7860
LFX Flow runtime (internal, no direct UI) localhost:6004
SQLite files backend/data/kirche.db (app), Langflow keeps its own file —

Why SQLite: a flow run needs only a handful of single-row statements, and Langflow itself runs on SQLite by default — so the whole stack works without a database server. Postgres can return later by changing DATABASE_URL (migrations stay portable).

.env holds only ubiquitous variables (identical value in dev and prod: secrets, service URLs). Dev-only variables travel via devcontainer.json (APP_ENV=dev); paths resolve from the repo root in code.

Getting Started

  1. Copy .env.example to .env and fill in the secrets.
  2. Open the repo in VS Code → "Reopen in Container". Setup installs dependencies and syncs backend/flows/; the entrypoints migrate and serve automatically.
  3. The stack is already running: UI at http://localhost:3000, API docs at http://localhost:8000/api/docs.

Development

Backend (attached api container, from backend/):

  • uv run pytest — full test suite (throwaway SQLite file, no external DB).
  • uv run alembic upgrade head — migrate the dev database.
  • uv run python scripts/sync_flows.py --sync — reconcile backend/flows/.
  • uv run python scripts/sync_flows.py --pull — export all Langflow flows into backend/flows/ first.
  • uv run python scripts/deploy_flow.py --langflow-id <uuid> — import one Langflow flow via the API.
  • uv run python scripts/make_flow_fixtures.py — regenerate the bundled flows (writes test fixtures and backend/flows/).
  • uv run python scripts/smoke_e2e.py — manual end-to-end smoke.

Frontend (node lives in the frontend container):

  • docker compose exec frontend npm run dev — HMR dev server (already running via compose; this is for a second instance or flags).
  • docker compose exec frontend npm run build — typecheck + build.
  • Without a docker socket: VS Code "Attach to Running Container" → frontend.

Flow workflow: design in Langflow → export into backend/flows/<name>.json (--pull, or UI download) → commit → the watcher deploys it automatically. Deleting a file removes the flow including its runs (git keeps the JSON).

Production (self-hosted, internal use — no TLS/reverse proxy included)

  1. Check out the repo on the host, create .env from .env.example with real secrets and FRONTEND_MODE=preview.
  2. docker compose up -d --build.
  3. Code updates via git pull + docker compose restart api frontend (the checkout is bind-mounted); image rebuilds only for dependency changes (docker compose up -d --build).

Container updates: registry images (langflowai/langflow:latest) auto-update nightly via Watchtower (nickfedor/watchtower). Locally built images (api, lfx, frontend) update with docker compose build --pull.

Continuous integration

Workflows in .forgejo/workflows/ run on Forgejo: backend pytest, frontend build, compose validation. They need a Runner with the docker label online (repo Settings → Actions → Runners) and action resolution for actions/checkout (github proxy or code.forgejo.org mirror).