Skip to content

Architecture overview

This page gives an overview of the KanzleiSynchron components and how they fit together locally. It is aimed at developers.

ComponentTechnologyPort (local)
FrontendNext.js (TypeScript), directory frontend/3013
Backend / APIRust, Axum, crate binary ks-api3030
DatabasePostgreSQL5433
IdentityOry 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.

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.

The backend is a Cargo workspace under backend/ with five crates (backend/Cargo.toml, members = ["api", "core", "db", "models", "sample-gen"]):

DirectoryCrate nameResponsibility
api/api (binary ks-api)Axum HTTP server: routes, auth, request handling. Entry point cargo run --bin ks-api.
core/app_coreDomain / business logic (reconciliation, exports, period logic).
db/dbDatabase access, migrations, sqlx wiring.
models/modelsShared data and error types (e.g. models::common::KsError).
sample-gen/sample-genGenerator 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.

  • Identities are managed via Ory Kratos; the login flow runs through the frontend (/api/auth/login).
  • The session is held in an HttpOnly ks_session cookie, scoped to :3013 and sent automatically to /api/*.
  • The backend derives the AuthUser (including tenant_id, user_id, role) from the session (backend/api/src/auth.rs).

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.

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).