# Astroklient — wdrożenie warstwy pośredniej Pełne funkcje astrologiczne, bez generowania tekstu i bez administracji. Trzeci produkt drabiny: **astrodemo** (dwie funkcje) → **astroklient** → **astrololo**. Host: `astroklient.czernobog.pl` · obraz `astrololo-astroklient` · port 8006. ## Jak to jest odizolowane Trzy granice, w kolejności od najmocniejszej: **Obraz.** Plików ekranów, których ten produkt nie ma, NIE MA w obrazie — usuwa je `usun.txt` przy budowaniu. Nie ma więc czego wyłączać ani czym odsłaniać: uprawnienia liczą się z katalogu funkcji, a katalog składa się ze zgłoszeń ekranów obecnych w obrazie. Test w repo aplikacji sprawdza to na złożonym drzewie, razem z zaporą słownikową — po nieobecnych funkcjach nie zostaje nawet słowo w komentarzu. **Udział NFS.** Własny `astrololo-klient`, osobny od produkcyjnego i od demo. Pule kont izolują klientów od siebie, ale to izolacja PROGRAMOWA — opiera się na poprawności mechanizmu pul. Granica na poziomie systemu plików nie zależy od tego, czy w kodzie niczego nie przeoczono. Przy sprzątaniu demo nie da się przez pomyłkę skasować cudzych danych, bo leżą gdzie indziej. **Warstwa danych i logiki.** Własna para `data-astroklient` + `logic-astroklient`, z silnikiem własnym (permisywnym) — silnik B (AGPL) nie wchodzi do produktu oddawanego klientom. --- ## Krok 1 — udział `astrololo-klient` na TrueNAS ```bash midclt call sharing.nfs.create '{ "path": "/mnt/Tank1/astrololo-klient", "hosts": ["192.168.1.73", "192.168.1.80", "192.168.1.81", "192.168.1.82"], "maproot_user": "root", "maproot_group": "root", "enabled": true }' midclt call service.restart nfs ``` **Wszystkie CZTERY węzły.** Klaster ma cztery (`kubectl get nodes -o wide`), a nie trzy — pominięcie jednego daje `access denied by server` dopiero wtedy, gdy scheduler tam coś postawi, czyli w losowym momencie tygodnie później. Kontrolę wyłapującą braki i literówki w adresach masz w [README.md](README.md) → „Kontrola: czy każdy udział obejmuje każdy węzeł". Jeśli katalog jeszcze nie istnieje, utwórz dataset przed eksportem. ## Krok 2 — konta klientów Każde konto to osobna pula, więc **rozdajesz konta, nie jedno hasło**. Wszystkie mają ten sam poziom dostępu — konta rozdziela się dla rozdzielenia plików, nie uprawnień. ```bash # skrypt w repo aplikacji; format hasha wspólny dla wszystkich usług python services/presentation/scripts/make_user.py klientA # wypisze: scrypt$… ``` ```bash kubectl -n astrololo create secret generic astrololo-astroklient \ --from-literal=ASTROKLIENT_USERS='klientA:scrypt$…,klientB:scrypt$…' \ --from-literal=SESSION_SECRET="$(openssl rand -hex 32)" ``` `SESSION_SECRET` jest **własny**, nie ten z pełnej aplikacji ani z demo: trzy produkty nie mają powodu uznawać nawzajem swoich sesji. Ciasteczko też ma własną nazwę (`astroklient_sesja`), więc logowanie do jednego nie wyrzuca z drugiego. **Pod bez `SESSION_SECRET` celowo nie wstanie** — logowanie bez klucza podpisu nie miałoby czym się bronić. ### Unieważnienie dostępu Nie ma wolumenu stanu, więc nie ma licznika pokolenia sesji. Zamiast tego: - usunięcie konta z `ASTROKLIENT_USERS` albo zmiana jego hasła **natychmiast ubija jego otwarte sesje** — odcisk poświadczenia w ciasteczku przestaje pasować, - rotacja `SESSION_SECRET` wylogowuje wszystkich naraz. **Pula zostaje na udziale.** Odebranie dostępu nie kasuje plików klienta — przestaje być tylko komu je pokazywać. ### Dodanie konta później ```bash STARE=$(kubectl -n astrololo get secret astrololo-astroklient -o jsonpath='{.data.ASTROKLIENT_USERS}' | base64 -d) kubectl -n astrololo create secret generic astrololo-astroklient \ --from-literal=ASTROKLIENT_USERS="${STARE},klientC:scrypt\$…" \ --dry-run=client -o yaml | kubectl apply -f - kubectl -n astrololo rollout restart deploy/astroklient ``` ## Krok 3 — wdrożenie Sekret i udział **muszą istnieć wcześniej**. Potem wystarczy merge do `master` — ArgoCD zsynchronizuje, a image-updater będzie odtąd podbijał tag sam, bo obraz jest dopisany do [`image-updater.yaml`](image-updater.yaml). ## Sprawdzenie po wdrożeniu ```bash kubectl -n astrololo get pods -l app=astroklient -o wide kubectl -n astrololo logs -l app=astroklient --tail=30 curl -sk https://astroklient.czernobog.pl/ -o /dev/null -w '%{http_code}\n' # 303 → bramka logowania odpowiada ``` Po zalogowaniu w nawigacji ma być **sześć** pozycji: Horoskop, Interpretacje, Kalendarz, Synastria, Sygnifikatory, Pliki. **Bez zalogowania każdy adres oddaje 303** — także nieistniejący. Bramka logowania działa przed trasowaniem, więc niezalogowany nie wyczyta z kodów odpowiedzi, które ekrany istnieją. Sprawdzanie nieobecnych adresów bez sesji nic więc nie mówi: pokaże 303 dla wszystkiego, łącznie z `/nie-ma-takiego-ekranu`. Sprawdzenie ma sens dopiero Z SESJĄ, i wtedy nieobecne ekrany dają **404, nie 403** — odmowa z powodem byłaby informacją, że coś tam jest: ```bash CIASTKO='astroklient_sesja=' for A in / /compile /settings /accounts /files; do printf "%-12s %s\n" "$A" \ "$(curl -sk -o /dev/null -w '%{http_code}' -H "Cookie: $CIASTKO" https://astroklient.czernobog.pl$A)" done # oczekiwane: / → 200, reszta → 404 ``` ## Import puli klienta do pełnej aplikacji Pula to zwykły katalog na udziale — kopiuje się go tak samo jak w demo, patrz [README-astrodemo.md](README-astrodemo.md) → „Import puli klienta". Ścieżka źródłowa to `/mnt/Tank1/astrololo-klient/`.