171 lines
8.5 KiB
Markdown
171 lines
8.5 KiB
Markdown
# 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).
|
|
|
|
## Future
|
|
|
|
Ideas and planned features live in [ROADMAP.md](ROADMAP.md)
|
|
(the single authoritative place for future implementation ideas).
|
|
|
|
## 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`.
|
|
|
|
```mermaid
|
|
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. LLM provider
|
|
keys for Langflow are plain env vars (`OPENAI_API_KEY`,
|
|
`OPENAI_BASE_URL`) — Langflow turns them into restart-proof global
|
|
variables, LFX reads them at runtime. `LANGFLOW_SECRET_KEY` must be a
|
|
valid Fernet key (see `.env.example`).
|
|
|
|
## 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 → press "Aus Langflow synchronisieren"
|
|
in Verwaltung (manual full pass: Langflow → `backend/flows/<name>.json` →
|
|
DB + LFX deploy) → commit. File-only alternatives: `scripts/sync_flows.py
|
|
--pull --sync`, UI download, or the single-flow import by Langflow ID. The
|
|
watcher deploys file edits automatically. Deleting a file removes the flow
|
|
including its runs (git keeps the JSON).
|
|
|
|
## Production (self-hosted — TLS/reverse proxy required, not included)
|
|
|
|
1. Check out the repo on the host, create `.env` from `.env.example` with
|
|
real secrets (`openssl rand -hex 32`) and `FRONTEND_MODE=preview`.
|
|
2. Validate it: `uv run python scripts/check_prod.py --env ../.env`
|
|
(run from `backend/`; blocks on weak secrets or dev modes).
|
|
3. `docker compose up -d --build`.
|
|
4. 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`).
|
|
|
|
Internet exposure checklist (both forwarded ports sit behind your HTTPS
|
|
proxy — nothing here substitutes for it):
|
|
|
|
- Proxy: force HTTPS (+ HSTS), and put an extra login (basic-auth or
|
|
OIDC) in front of Langflow `:7860`. Langflow has a history of
|
|
critical unauthenticated RCEs — treat its UI as privileged tooling,
|
|
never share flows publicly ("Shareable Playground" = RCE risk).
|
|
- Secrets: all `*_KEY`/`*_TOKEN`/`*_PASSWORD` long and random; rotate
|
|
after any incident or staff change; re-run `check_prod.py`.
|
|
- Langflow/LFX upgrades (pinned in lockstep): bump `LANGFLOW_VERSION`
|
|
(`.env`), `Dockerfile.lfx` ARG, and backend `lfx~=` together, then
|
|
`lfx upgrade --upgrade-flow=safe` + `lfx validate --level 4` on
|
|
`backend/flows/*.json`. Check Langflow security advisories monthly.
|
|
- Backups: `backend/data/` (SQLite) and the `langflow-data` volume.
|
|
|
|
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).
|