Architektur
PostGIS + QGIS
QGIS (lokal) → TLS 1.3 + Client-Zertifikat → PgBouncer (mTLS) → PostGIS (nur Compose-Netz)
Browser → HTTPS → Next.js → FastAPI → PostGIS
Editor/Field → HTTPS → FastAPI → PostGIS (postgres:5432)
- SSOT: Postgres/PostGIS — nicht die QGIS-Projektdatei.
- QGIS: Operatives UI für Erfassung und Karte. Schema anwenden im Plugin (
GET /qgis/layers, Viewsqgis_<kind>, Filterproject_id). Stammdaten bleiben im Web-CMS. - Geo: PostGIS, SRID 25832.
- DB-Rollen: Control-Plane
linetra_edit/linetra_readnur auf DBlinetra. QGIS und Fach-API verbinden als{slug}_edit/{slug}_readauflinetra_<slug>(ADR-0031). Superuserpostgresnur Admin/Restore. Cert-CN = Mandanten-Rolle, nicht pro Person. - Netz (Soll, live): PostGIS unpublished. QGIS über PgBouncer mTLS (
sslmode=verify-full). Production-FastAPI internpostgres:5432. Workstation-Development darf denselben Proxy nutzen (ADR-0013). WireGuard darf für andere NAS-Dienste bleiben, ist keine Voraussetzung für QGIS oder die Apps (ADR-0003). - Netz (Ist, abgeschaltet): Traefik TCP
:3401aufwg0(plain, geteiltes Passwort).docker-compose.override.ymlist nicht mehr der QGIS-Pfad.
Lokal darf Compose Postgres weiter auf localhost:3401 legen — das ist nicht das Server-Soll.
Web-CMS
FastAPI + Next.js auf demselben PostGIS:
| Service | Rolle |
|---|---|
postgres |
PostGIS SSOT (postgis/postgis:17-3.5), unpublished |
pgbouncer |
mTLS-Auth-Proxy für QGIS (Profil mtls) |
backend |
FastAPI JSON API (/api/v1/…), dual DB engines + app_users |
frontend / frontend-prod |
Next.js Webapp (dev / production) auf linetra-web.nasarek.dev |
marketing / marketing-prod |
Öffentliche Produktseite (Preise, Kontakt, Rechtliches) auf linetra-org.nasarek.dev |
redis |
Broker + Result-Backend |
celery |
Ingest, GIS-Import, Produkt-PDF, .ltp / QGIS-Export |
docs |
Zensical unter /documentation/ (über die Webapp) |
Browser → Traefik (linetra-web.nasarek.dev) → Next.js Webapp → /api proxy → FastAPI → PostGIS
Browser → Traefik (linetra-org.nasarek.dev + Basic Auth) → Next.js Marketing
QGIS → PgBouncer :5432 (TLS inside PgBouncer, kein Traefik-TLS) → PostGIS
Zwei getrennte Identitätsebenen:
| Ebene | Identitäten | Zweck |
|---|---|---|
| DB-Rollen | {slug}_edit / {slug}_read auf der Mandanten-DB; Control: linetra_edit / linetra_read |
Postgres-Login für QGIS (Cert-CN) und API-Engines |
| Linetra-Nutzer | Tabelle app_users (Control-DB, tenant_id = Organisationskonto) |
Web-Login; Org-Rollen admin/editor/reader (ADR-0032) |
- Auth:
app_users+ argon2, signed session cookie + CSRF; erster Admin/Editor per Bootstrap ausLINETRA_BOOTSTRAP_*(nicht aus den DB-Rollen). - Admin/Editor → Edit-Engine; Reader → Read-Engine.
- Stammdaten CRUD in the web app; GIS-Write im Editor (FastAPI) oder QGIS (Proxy). Web
/mapist OpenLayers + MVT, nur lesen. Stamm:geo_objects+ Schema-CMS; QGIS schreibtqgis_<kind>(ADR-0049, ADR-0050). - Redis / Celery / hosted Docs: Compose-Services; Entscheidungen unter ADRs.
Produkt-IA: .cursor/rules/product-ux-contracts.mdc, site-shell.mdc. Editor: linetra-editor/README.md. Entscheidungen: ADRs.
Workflow
DB → QGIS (Geo write) / Web-CMS (Stammdaten + read-only map) → Reports / PDF
Jira-Import und weitere Geo-Layer/Tiles im Web sind bewusst später.