diff --git a/docs/architektura-dwoch-silnikow.md b/docs/architektura-dwoch-silnikow.md new file mode 100644 index 0000000..f376392 --- /dev/null +++ b/docs/architektura-dwoch-silnikow.md @@ -0,0 +1,84 @@ +# Architektura dwóch silników (warstwa logiczna) + +Dokument roboczy. Decyzja: warstwa logiczna ma **dwie wymienne implementacje silnika obliczeń** — jedną **własną/permisywną** (ścieżka A) i jedną **opartą o AGPL** (ścieżka C, Swiss Ephemeris) — żeby od pierwszego dnia mieć **wbudowany framework porównań i walidacji**. Warstwy **prezentacji i danych pozostają wspólne i pojedyncze**; rozdwaja się wyłącznie silnik wewnątrz warstwy logicznej. + +--- + +## 1. Schemat + +``` + (jedna) (jedna, ale 2 silniki) (jedna) +┌──────────────────────┐ ┌─────────────────────────────────────┐ ┌──────────────────────┐ +│ PREZENTACJA │ ─────▶ │ LOGIKA │ ─────▶ │ DANE │ +│ (bez zmian) │ ◀───── │ EngineProvider (interfejs) │ ◀───── │ (bez zmian) │ +└──────────────────────┘ │ ├── EngineA: własny (permisywny)│ └──────────────────────┘ + │ │ Skyfield/Moshier — in-proc │ + │ └── EngineB: swisseph (AGPL) │ + │ ⇢ OSOBNY proces/usługa │ + │ Komparator (dual-run + raport) │ + └─────────────────────────────────────┘ + │ + ⇢ (granica sieciowa/IPC) + ┌─────────────────────────────────┐ + │ engine-swisseph (AGPL, OSOBNO) │ + │ pyswisseph / Swiss Ephemeris │ + └─────────────────────────────────┘ +``` + +Prezentacja i dane „widzą" tylko interfejs `EngineProvider` — **nie wiedzą, który silnik liczy** (engine‑agnostic). To ta sama zasada modułowości co `DataProvider` w warstwie danych. + +--- + +## 2. Po co dwa silniki + +1. **Wyrocznia walidacyjna od dnia zero.** Każdy wynik EngineA możemy natychmiast porównać z EngineB (Swiss Ephemeris = de‑facto standard). Bezcenne przy budowie własnego silnika od zera (primary directions, domy, węzły/Lilith). +2. **Framework porównań.** Tryb „policz oboma i pokaż różnice" — do testów regresyjnych (CI) i do podglądu side‑by‑side w UI. +3. **Bezpieczeństwo decyzji.** Gdyby własny silnik gdzieś odstawał, widać to od razu, a nie po miesiącach. + +--- + +## 3. Izolacja licencyjna (warunek konieczny) ⚠️ + +EngineB jest **AGPL**, więc nie może być wlinkowany w permisywny produkt. Rozwiązanie zgodne z naszą architekturą (osobne usługi jak warstwa danych): + +- **EngineB = osobny proces/usługa `engine-swisseph`**, wołany przez **granicę sieciową/IPC** (HTTP). Brak linkowania = brak „zarażenia" copyleftem reszty. +- **Produkt zamknięty (dystrybucja/hosting):** prezentacja + logika(**EngineA**) + dane. **Bez** EngineB. Zero AGPL. +- **Profil porównawczy/dev/CI:** dodatkowo uruchamiamy usługę `engine-swisseph` (AGPL, sama w sobie zgodna z AGPL — to w zasadzie cienkie API na pyswisseph). Używana wewnętrznie do porównań, nie wystawiana użytkownikom produktu. +- **Konfiguracja** decyduje, czy EngineB jest w ogóle dostępny (`ENGINE_B_URL` ustawione lub nie). + +Efekt: pełny framework porównań **bez** narażania kodu i danych produktu na obowiązki AGPL (patrz `przeglad-bibliotek-i-licencji.md` oraz analiza zakresu AGPL względem baz danych). + +--- + +## 4. Jak działa porównanie (dual‑run) + +1. To samo wejście (dane horoskopu + ustawienia) trafia do EngineA i EngineB. +2. Komparator zestawia wyniki: pozycje obiektów, cusps domów, aspekty, daty technik. +3. Różnice liczone z **progami tolerancji per wielkość** (np. długość ekliptyczna ≤ 1″, cusp ≤ 1″, data zdarzenia ≤ 1 min); przekroczenia oflagowane. +4. Raport: (a) jako asercje w **CI** (regresja), (b) jako **podgląd side‑by‑side** w prezentacji na żądanie. + +--- + +## 5. Wpływ na warstwy i mapowanie na wymagania + +| Warstwa | Zmiana | +|---|---| +| Prezentacja | brak (opcjonalnie: widok porównawczy side‑by‑side) | +| Dane | brak | +| **Logika** | `EngineProvider` + 2 backendy (EngineA in‑proc, EngineB jako klient usługi AGPL) + komparator | +| **Nowa usługa** | `engine-swisseph` (AGPL, osobno, opcjonalna) | + +Wymagania (arkusz „Warstwa logiczna"): +- **LOG‑24** — interfejs `EngineProvider` z **dwoma** backendami (zrewidowane). +- **LOG‑25** — framework walidacyjno‑porównawczy (zrewidowane). +- **LOG‑26** — tryb dual‑run + raport różnic (nowe). +- **LOG‑27** — izolacja licencyjna silnika AGPL jako osobnej usługi (nowe). +- **LOG‑28** — kontrakt parzystości silników: identyczny interfejs, te same testy (nowe). + +--- + +## 6. Implikacje wdrożeniowe + +- **Dwa profile `docker-compose`:** `proprietary` (prezentacja+logika+dane, EngineA) i `comparison` (dodaje `engine-swisseph`). +- **Testy kontraktowe** uruchamiane na obu silnikach (ten sam zestaw → gwarancja parzystości interfejsu). +- **Decyzja A vs B na produkcji** pozostaje po stronie A; B nigdy nie trafia do dystrybucji zamkniętej — służy jako wzorzec i narzędzie QA. diff --git a/docs/astrololo_wymagania.xlsx b/docs/astrololo_wymagania.xlsx index 9e6073f..12501a9 100644 Binary files a/docs/astrololo_wymagania.xlsx and b/docs/astrololo_wymagania.xlsx differ