Wiki
Architektura QuoteNode
Techniczny przegląd architektury systemu QuoteNode: backendu, frontendu, bazy danych i modelu wdrożenia.
Architektura QuoteNode
QuoteNode to aplikacja single-tenant zaprojektowana do wdrożeń self-hosted. Każda instancja jest odseparowana i ma własną bazę danych, własne przechowywanie plików oraz własne procesy aplikacyjne.
Przegląd systemu
Przeglądarka klienta
│
▼
Caddy (Reverse Proxy, HTTPS)
│
├── /api/* → Spring Boot Backend (Java 25)
├── /offer/* → Spring Boot Backend (publiczne strony ofert)
└── /* → Vue 3 Frontend (Vite, SPA)
│
▼
PostgreSQL 16
Backend
Backend jest aplikacją Java 25 zbudowaną na Spring Boot 4. Odpowiada za:
- REST API — całą logikę biznesową wystawioną przez wersjonowane endpointy
- Uwierzytelnianie — model sesyjny z szyfrowanymi cookie i 2FA (TOTP)
- Autoryzację — kontrolę dostępu opartą o role z walidacją per endpoint
- Dostęp do bazy — Spring Data JPA oraz migracje Flyway
- Generowanie PDF — szablony Thymeleaf renderowane do HTML i zamieniane na PDF przez Gotenberg
- E-mail — asynchroniczną integrację SMTP z retry i logowaniem
- Publiczne strony ofert — server-rendered HTML dla linków klientowskich
- Log audytowy — append-only tracking zmian
- Scheduler — zadania tła dla wygasania ofert, anonimizacji IP i digestów powiadomień
Najważniejsze decyzje projektowe:
- Brak multi-tenancy — aplikacja obsługuje dokładnie jedną organizację. Upraszcza to model bezpieczeństwa i usuwa złożoność izolacji tenantów.
- Migracje Flyway — zmiany schematu są wyłącznie addytywne. Kolumny nie są usuwane; zamiast tego dostają prefiks
deprecated_. - Niemutowalne snapshoty — dane oferty są utrwalane jako snapshot JSON w momencie wysłania. PDF-y są zawsze renderowane ze snapshotów, a nie z live data.
- Deterministyczny pricing — wszystkie wyliczenia mają zdefiniowaną kolejność i konfigurowalne zaokrąglenia. Wyniki są przechowywane do celów audytowych.
Frontend
Frontend to aplikacja Vue 3 SPA budowana przez Vite:
- UI framework — biblioteka komponentów PrimeVue 4
- Styling — Tailwind CSS 4
- Stan — store’y Pinia 3
- Routing — Vue Router 5 z guardami zależnymi od ról
- i18n — vue-i18n z lokalizacjami angielską i polską
- Klient API — typowany klient HTTP wywołujący backendowe REST API
Frontend jest serwowany jako statyczne assety przez Caddy. Komunikuje się z backendem wyłącznie przez REST API.
Baza danych
PostgreSQL 16 jest jedyną wspieraną bazą danych:
- Zarządzanie schematem — migracje Flyway uruchamiane automatycznie przy starcie backendu
- Kluczowe encje — customers, contacts, offers, offer items, products, pricing rules, users, audit logs, notifications
- Denormalizacja — sumy ofert są utrwalane w osobnej tabeli dla szybkiego queryowania
- Widoki — widok pipeline ofert z lateral joinem do najnowszych kursów FX
Generowanie PDF
Generowanie PDF działa w pipeline dwustopniowym:
- Thymeleaf renderuje snapshot oferty do dokumentu HTML z inline CSS
- Gotenberg zamienia HTML na gotowy do druku PDF
Obsługiwane są dwa tryby:
- Synchroniczny — dla ofert z mniej niż 50 pozycjami PDF powstaje inline, zwykle poniżej 3 sekund
- Asynchroniczny — dla dużych ofert zadanie PDF trafia do background workera, a użytkownik dostaje powiadomienie po zakończeniu
Wdrożenie
QuoteNode jest wdrażany przez Docker Compose:
- Kontener backendu — Java 25 (Eclipse Temurin)
- Kontener frontendu — Node 24 + Vite dev server w development albo statyczny build w produkcji
- Kontener bazy — PostgreSQL 16
- Reverse proxy — Caddy 2 z automatycznym HTTPS
- Silnik PDF — Gotenberg
- Testowanie maili — Mailpit tylko w środowiskach developerskich
Cały stack działa jako jeden projekt Docker Compose bez zależności od zewnętrznych usług. Może pracować także w środowiskach air-gapped.
Licencjonowanie
Licencje mają postać plików podpisanych Ed25519 i są weryfikowane offline. System sprawdza:
- edycję (Free, Pro, Business, Enterprise),
- maksymalną liczbę użytkowników,
- datę wygaśnięcia,
- feature flagi, takie jak white-label i advanced templates.
Nie ma żadnego połączenia z zewnętrznym serwerem licencyjnym. Wygaśnięta licencja nie wyłącza funkcji — jedynym skutkiem jest badge “Powered by QuoteNode” na powierzchniach klientowskich i przypomnienie o odnowieniu w UI.