Pokaż spis treści

ExKSeF technicznie

Architektura, kod i deploy pokazane jak produkt

  • Domain i use case'y odseparowane od hostów, EF Core i SDK KSeF
  • Web, scheduler i PDF jako oddzielne procesy Dockera
  • Gitea Actions buduje wersjonowane obrazy i deployuje wiele instancji
  • Testy jednostkowe, integracyjne i architektoniczne utrzymują kierunek zmian

Dlaczego warto pokazać technikalia osobno

ExKSeF jest aplikacją, w której widoczny ekran jest tylko końcówką większego procesu. Lista faktur, płatności albo harmonogram nie działa samodzielnie: za nimi stoją use case'y, porty integracyjne, reguły domenowe, repozytoria, joby i wdrożenie utrzymujące web oraz procesy w tle w tej samej konfiguracji.

Strona techniczna jest potrzebna, bo pokazuje nie tylko co robi produkt, ale jak został zbudowany. Dla potencjalnego pracodawcy to ważniejsze niż kolejna lista funkcji: widać tu separację odpowiedzialności, odporność na rozjazd konfiguracji, świadome bramki bezpieczeństwa, automatyzację deployu i miejsca, gdzie testy zamrażają reguły architektury.

Zakres techniczny pokazany na stronie

  • Warstwy aplikacji - domena i use case'y w Application, persistence i adaptery poza logiką biznesową, hosty Web/Scheduler jako wejścia do systemu.

  • Integracje - KSeF, KSeF Lighthouse, VAT Whitelist, CEIDG, KRS, Pekao Connect, PDF service, e-mail, SMS i push podłączone przez kontrakty albo dedykowane adaptery.

  • Procesy runtime - web obsługuje UI i API dla mobile, scheduler wykonuje joby, PDF service renderuje dokumenty jako osobny proces Node.

  • Deploy - Gitea Actions liczy wersję, buduje trzy obrazy, publikuje je do rejestru i wdraża instancje na podstawie osobnych sekretów środowiskowych.

Architektura runtime

%%{init: {"themeVariables": {"fontSize": "15px"}}}%%
flowchart TD
  U[Operator web] --> W[Blazor Server Web]
  M[Aplikacja mobilna] --> API[Minimal API /api]
  API --> W
  W --> APP[Application: use case'y i domena]
  S[Scheduler host] --> APP
  APP --> PORTY[Kontrakty i porty]
  PORTY --> DB[(SQLite / data volume)]
  PORTY --> KSEF[KSeF i KSeF Lighthouse]
  PORTY --> VAT[Biała lista VAT]
  PORTY --> PEKAO[Pekao Connect]
  PORTY --> MAIL[E-mail / SMS / Push]
  W --> PDF[PDF service Node]
  S --> LOG[Historia jobów i heartbeat]
  APP --> LOG

Prezentacja techniczna

01 proces

1 / 10

Warstwy kodu i odpowiedzialności

Repozytorium jest podzielone według odpowiedzialności, a nie według przypadkowych folderów. Solution zawiera projekty Application, Client, Infrastructure, Adapters, Scheduler, Mocks oraz testy jednostkowe i integracyjne. Ten podział jest widoczny w kodzie i potwierdzony testami architektonicznymi.

Application

To miejsce dla domeny, kontraktów i use case'ów. W tej warstwie mieszczą się reguły płatności, faktur, kontrahentów, ról, schedulerów i integracji rozumianych jako porty. Application nie powinien wiedzieć, czy wywołanie przyszło z Blazora, mobile API, schedulera czy testu.

Infrastructure i Adapters

Persistence odpowiada za EF Core, migracje, repozytoria, eksporty i wspólny dostęp do bazy. Adaptery realizują komunikację z zewnętrznymi systemami: KSeF, KSeF Lighthouse, VAT Whitelist, CEIDG, KRS, Banking i Pekao Connect. Dzięki temu reguły biznesowe mogą operować na kontraktach zamiast na szczegółach transportu.

Hosty

Web host składa UI, autoryzację, endpointy API dla Fluttera, antiforgery dla UI, rate limiting logowania, nagłówki bezpieczeństwa, forwarded headers pod reverse proxy i rejestrację use case'ów. Scheduler host składa te same rdzenie persistence, KSeF, XML, VAT, banking i Pekao Connect, ale uruchamia je przez joby oraz własny kontekst systemowego użytkownika.

Testy architektoniczne

Projekt ma osobny pakiet testów architektonicznych oparty o NetArchTest. Pilnuje on, żeby domena nie zależała od EF Core, Infrastructure ani ASP.NET Core, a Application nie zależał od ASP.NET Core, EF Core ani SDK klienta KSeF. To konkretna ochrona przed przypadkowym rozmyciem warstw podczas kolejnych zmian.

Pipeline Gitea i wdrożenie

%%{init: {"themeVariables": {"fontSize": "15px"}}}%%
flowchart TD
  A[Push do main] --> B[Checkout z submodules]
  B --> C[Wersja = VERSION + liczba commitów]
  C --> D[Docker login do registry.darweb.eu]
  D --> E[Build web image]
  D --> F[Build scheduler image]
  D --> G[Build pdf image]
  E --> H[Push tag: wersja, SHA, latest]
  F --> H
  G --> H
  H --> I[Deploy instancji]
  I --> J[Przygotowanie /opt/*, data, logs, keys]
  J --> K[.env z sekretu Gitea + IMAGE_TAG + APP_VERSION]
  K --> L[docker compose pull]
  L --> M[docker compose up -d --force-recreate]

Deploy produkcyjny bez ręcznego składania paczek

Workflow Gitea `Deploy exksef` startuje po pushu do gałęzi `main`. Najpierw liczy wersję z pliku `VERSION`, liczby commitów i krótkiego SHA, a potem buduje trzy obrazy: web, scheduler i pdf. Każdy obraz dostaje tag wersji, SHA oraz `latest`, po czym trafia do `registry.darweb.eu`.

Wdrożenie nie polega na kopiowaniu lokalnej aplikacji na serwer. Pipeline przygotowuje katalog instancji w `/opt`, zapisuje plik Firebase service account z sekretu, ustawia katalogi `data`, `logs` i `keys` pod UID 1654, kopiuje `docker-compose.deploy.yml`, tworzy `.env` z odpowiedniego sekretu instancji i dopisuje `IMAGE_TAG` oraz `APP_VERSION`.

Wiele instancji z tego samego artefaktu

Ten sam zestaw obrazów jest wdrażany do kilku środowisk: `fuz`, `auravita`, `demo`, `matea` i `duet`. Różni je konfiguracja w sekretach, katalog danych, certyfikaty i nazwa projektu compose. To ważny element architektury, bo produkt może obsługiwać różne firmy bez utrzymywania osobnych gałęzi albo ręcznie zmienianych paczek.

Kontener runtime

Compose produkcyjny uruchamia trzy kontenery: `web`, `scheduler` i `pdf`. Web i scheduler współdzielą wolumeny danych, logów, kluczy Data Protection oraz certyfikatów Pekao Connect w trybie read-only. Oba procesy mają ustawione `TZ`, `APP_VERSION`, konfigurację integracji i endpoint serwisu PDF. PDF service działa jako osobny kontener Node i jest widoczny dla weba oraz schedulera po nazwie compose.

Proces wytwarzania kodu

Technicznie projekt jest prowadzony tak, żeby zmiana funkcjonalna przechodziła przez kilka poziomów kontroli: zrozumienie procesu biznesowego, zmiana use case'u lub domeny, podłączenie do web/mobile/schedulera, aktualizacja uprawnień oraz testy tam, gdzie ryzyko jest największe.

Typowy przebieg zmiany

  1. Reguła domenowa - najpierw trzeba ustalić, czy zmiana dotyczy statusu faktury, płatności, kontrahenta, uprawnienia, schedulera czy integracji.

  2. Use case - operacja trafia do Application, żeby dało się ją wywołać z weba, API mobile albo joba bez kopiowania logiki.

  3. Adapter albo persistence - jeśli zmiana dotyka bazy, KSeF, banku, PDF lub zewnętrznego słownika, implementacja zostaje po stronie infrastruktury.

  4. UI i API - web i mobile pokazują tylko dostępne akcje, a API nadal broni dostępu i spójności danych.

  5. Testy - testy jednostkowe sprawdzają reguły, integracyjne pilnują trudnych przepływów Pekao Connect, a architektoniczne bronią kierunku zależności.

  6. Deploy - po merge/push na `main` Gitea buduje obrazy i odtwarza instancje z wersją zapisaną w konfiguracji runtime.

Dlaczego to dobrze wygląda w prezentacji

Ta część portalu nie musi opowiadać o każdym pliku. Wystarczy pokazać, że projekt ma realne granice odpowiedzialności, automatyzację wydania, wiele procesów runtime, wieloinstancyjność oraz testy zabezpieczające najważniejsze decyzje. To są elementy, które odróżniają dojrzałą aplikację biznesową od prototypu.