Architecture overview
This page gives an overview of the KanzleiSynchron components and how they fit together locally. It is aimed at developers.
Components
Section titled “Components”| Component | Technology | Port (local) |
|---|---|---|
| Frontend | Next.js (TypeScript), directory frontend/ | 3013 |
| Backend / API | Rust, Axum, crate binary ks-api | 3030 |
| Database | PostgreSQL | 5433 |
| Identity | Ory Kratos (via Docker) | 4433 / 4434 |
Locally the whole stack starts via ./ks-run.sh (see Local development). PostgreSQL and Kratos run via infra/docker-compose.yml; the backend and frontend run natively.
Request flow
Section titled “Request flow”All work happens on :3013. The frontend calls its API over the same-origin path /api/* (NEXT_PUBLIC_API_URL=/api). next.config.ts rewrites /api/* server-side to BACKEND_INTERNAL_URL (locally http://localhost:3030).
Browser ──/api/*──▶ Next.js (:3013) ──rewrite──▶ ks-api (Axum, :3030) ──▶ PostgreSQL (:5433)This same-origin setup is deliberate: the browser sends the HttpOnly ks_session cookie only to /api/* (scoped to :3013). A direct cross-origin call to the backend would not carry the cookie.
Backend workspace (Rust)
Section titled “Backend workspace (Rust)”The backend is a Cargo workspace under backend/ with five crates (backend/Cargo.toml, members = ["api", "core", "db", "models", "sample-gen"]):
| Directory | Crate name | Responsibility |
|---|---|---|
api/ | api (binary ks-api) | Axum HTTP server: routes, auth, request handling. Entry point cargo run --bin ks-api. |
core/ | app_core | Domain / business logic (reconciliation, exports, period logic). |
db/ | db | Database access, migrations, sqlx wiring. |
models/ | models | Shared data and error types (e.g. models::common::KsError). |
sample-gen/ | sample-gen | Generator for sample / test data. |
The API routes live under backend/api/src/routes/ — including uploads, exceptions, periods, reports, exports, handoff, stb, settings, admin, ops, privacy, audit_pack.
Authentication
Section titled “Authentication”- Identities are managed via Ory Kratos; the login flow runs through the frontend (
/api/auth/login). - The session is held in an HttpOnly
ks_sessioncookie, scoped to:3013and sent automatically to/api/*. - The backend derives the
AuthUser(includingtenant_id,user_id,role) from the session (backend/api/src/auth.rs).
Tenant isolation & roles
Section titled “Tenant isolation & roles”KanzleiSynchron is multi-tenant: imports, reconciliations, exceptions, and handoff packs are strictly separated per client (Mandant). Every backend query filters on the tenant_id from the AuthUser.
Permissions follow a two-axis role model (tenant roles such as reviewer / merchant_admin and internal ops roles). Details and the full matrix: Roles & capabilities.
Handoff pack
Section titled “Handoff pack”The 6-file handoff pack is built in backend/api/src/routes/handoff.rs in one transaction (POST /handoff/:period_id/build-pack) and persisted to handoff_pack_files. The files: UStVA-preview.xml, BWA.pdf, ZM-EU-recap.csv, DATEV-EXTF.csv, audit-log.jsonl, and manifest.sha256. The DATEV-EXTF export follows format v7.0 (backend/api/src/routes/exports.rs).