From 82c73f6aa58dae7bc85c1b3af040de2e2fe1853d Mon Sep 17 00:00:00 2001 From: migatu Date: Mon, 17 Aug 2026 18:39:48 +0200 Subject: [PATCH 1/4] =?UTF-8?q?feat(astroklient):=20wdro=C5=BCenie=20wersj?= =?UTF-8?q?i=20demonstracyjnej=20(PRE-28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deployment + Service (ClusterIP), wpięcie w kustomization, obraz dopisany do image-updatera i runbook. Obraz na liście image-updatera CELOWO od razu: obraz, którego tam nie ma, nigdy się nie podbije, choćby CI go budowało — tak przez chwilę wisiał render na :latest. Token międzywarstwowy i klucz łącza brane z TYCH SAMYCH sekretów co prezentacja: demo nie jest furtką omijającą ochronę warstwy logicznej. Hasło demo natomiast z OSOBNEGO sekretu astrololo-demo — demo odcina się jego skasowaniem, bez ruszania kont głównej aplikacji. Limit żądań niższy niż w pełnej aplikacji (60/min): demo bywa udostępniane szerzej, a każde zapytanie sięga do treści baz. Runbook zaczyna się od ostrzeżenia, bo to jedyna rzecz, którą trzeba pamiętać za każdym razem: demo pracuje na PRODUKCYJNEJ warstwie danych, więc kto dostaje adres, czyta oryginalne bazy, a jego wgrania trafiają do produkcyjnego zbioru. Pełna izolacja wymagałaby osobnej warstwy danych i nie jest dziś zrobiona. Co-Authored-By: Claude Opus 5 --- astrololo/README-astroklient.md | 86 +++++++++++++++++++++++++++++++++ astrololo/README.md | 8 +++ astrololo/astroklient.yaml | 70 +++++++++++++++++++++++++++ astrololo/image-updater.yaml | 4 ++ astrololo/kustomization.yaml | 3 ++ 5 files changed, 171 insertions(+) create mode 100644 astrololo/README-astroklient.md create mode 100644 astrololo/astroklient.yaml diff --git a/astrololo/README-astroklient.md b/astrololo/README-astroklient.md new file mode 100644 index 0000000..801c50c --- /dev/null +++ b/astrololo/README-astroklient.md @@ -0,0 +1,86 @@ +# astroklient — wdrożenie wersji demo (PRE-28) + +Osobna usługa o dwóch funkcjach: **dodanie pliku bazy** i **zapytanie o +interpretację urodzeniową**. Opis samej aplikacji: `services/astroklient/README.md` +w repo aplikacji. + +--- + +## ⚠️ Przeczytaj, zanim komuś dasz adres + +Demo pracuje na **produkcyjnej warstwie danych**. To była świadoma decyzja, ale +niesie dwie konsekwencje, o których trzeba pamiętać za każdym razem: + +* **kto ma dostęp do demo, czyta Twoje oryginalne bazy interpretacyjne** — czyli + rdzeń produktu, którego pilnują LOG-32, DAN-25 i PRE-27, +* **pliki wgrane przez demo trafiają do produkcyjnego zbioru** i od razu biorą + udział w wyszukiwaniu, także w pełnej aplikacji. + +Jeśli demo ma trafić do kogoś spoza kręgu zaufania, właściwą odpowiedzią jest +osobna warstwa danych z pustym udziałem — **nie jest to dziś zrobione**. + +--- + +## Krok 1 — sekret z hasłem demo + +Osobny sekret, nie `astrololo-auth`. Dzięki temu demo odcina się **jedną komendą**, +bez ruszania kont głównej aplikacji i bez zmiany hasła komukolwiek. + +```bash +read -rs -p "Hasło do demo (DEMO_PASSWORD): " DEMO; echo + +kubectl -n astrololo create secret generic astrololo-demo \ + --from-literal=DEMO_PASSWORD="$DEMO" + +unset DEMO +``` + +Login to `demo` (zmienny przez `DEMO_USER` w `astroklient.yaml`). + +Hasło może być też hashem `scrypt$…` — wtedy nie leży nigdzie jawnie: + +```bash +cd services/presentation && python scripts/make_user.py demo # w repo aplikacji +``` + +--- + +## Krok 2 — wdrożenie + +```bash +kubectl apply -k astrololo +kubectl -n astrololo rollout status deploy/astroklient +``` + +Image-updater ma astroklienta na liście, więc kolejne obrazy podbiją się same. + +--- + +## Krok 3 — wejście z zewnątrz + +Usługa jest `ClusterIP`; z zewnątrz wchodzi się **wyłącznie przez Ingress po +https**, tak samo jak do prezentacji. Dopisz regułę do `ingress.yaml` — osobny +host albo ścieżka, zależnie od tego, jak chcesz demo udostępniać. + +Na czas sprawdzenia wystarczy tunel: + +```bash +kubectl -n astrololo port-forward deploy/astroklient 8005:8005 +``` + +i `http://localhost:8005` — login `demo`, hasło z kroku 1. + +--- + +## Odcięcie demo + +```bash +kubectl -n astrololo delete secret astrololo-demo +kubectl -n astrololo rollout restart deploy/astroklient +``` + +> Uwaga: **pod bez sekretu nie wstanie** i to jest zachowanie zamierzone. +> Alternatywnie `kubectl -n astrololo scale deploy/astroklient --replicas=0`, +> jeśli chcesz tylko wyłączyć, zachowując konfigurację. + +Konta głównej aplikacji pozostają nietknięte w obu przypadkach. diff --git a/astrololo/README.md b/astrololo/README.md index d887e7f..dda4149 100644 --- a/astrololo/README.md +++ b/astrololo/README.md @@ -29,6 +29,14 @@ Runbook: **[README-pliki.md](README-pliki.md)**. Ekran „Pliki" wymaga zapisu d udziału z bazami, więc znosi gwarancję z DAN-25, że baz nie da się zmienić przez NFS. Co zostaje z zabezpieczeń i jak to wdrożyć — w runbooku. +## astroklient — wersja demo (PRE-28) + +Osobna usługa o dwóch funkcjach. Runbook: **[README-astroklient.md](README-astroklient.md)**. + +⚠️ Pracuje na **produkcyjnej warstwie danych** — kto ma dostęp do demo, czyta +oryginalne bazy. Konto jest osobne (`astrololo-demo`), więc odcina się bez ruszania +kont głównej aplikacji. + ## ⚠️ Sekret `astrololo-auth` — utwórz PRZED wdrożeniem Aplikacja wystawia treść **oryginalnych baz interpretacyjnych**, dlatego wymaga diff --git a/astrololo/astroklient.yaml b/astrololo/astroklient.yaml new file mode 100644 index 0000000..e6a7003 --- /dev/null +++ b/astrololo/astroklient.yaml @@ -0,0 +1,70 @@ +# astroklient — wersja demonstracyjna (PRE-28). +# +# Osobna usługa o DWÓCH funkcjach: dodanie pliku bazy i zapytanie o interpretację +# urodzeniową. Pozostałe funkcje nie są tu ukryte — nie ma ich w obrazie. +# +# ⚠️ PRACUJE NA PRODUKCYJNEJ WARSTWIE DANYCH (świadoma decyzja właściciela). +# Kto ma dostęp do demo, czyta oryginalne bazy interpretacyjne, a pliki przez nie +# wgrane trafiają do produkcyjnego zbioru. Dlatego konto jest OSOBNE: demo odcina +# się skasowaniem sekretu astrololo-demo, bez ruszania kont głównej aplikacji. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: astroklient + namespace: astrololo +spec: + replicas: 1 + selector: + matchLabels: { app: astroklient } + template: + metadata: + labels: { app: astroklient } + spec: + containers: + - name: astroklient + image: gitea.czernobog.pl/gitea/astrololo-astroklient:latest + ports: [{ containerPort: 8005 }] + env: + - name: LOGIC_URL + value: "http://logic:8001" + # Konto demo — WŁASNE, nie astrololo-auth. Sekret tworzony POZA repo + # (jak pozostałe), patrz README-astroklient.md. + - name: DEMO_USER + value: "demo" + - name: DEMO_PASSWORD + valueFrom: + secretKeyRef: { name: astrololo-demo, key: DEMO_PASSWORD } + # Token międzywarstwowy i klucz łącza — TE SAME co prezentacja: + # demo nie jest furtką omijającą ochronę warstwy logicznej. + - name: INTERNAL_TOKEN + valueFrom: + secretKeyRef: { name: astrololo-auth, key: INTERNAL_TOKEN } + - name: LINK_KEY_PRESENTATION_LOGIC + valueFrom: + secretKeyRef: { name: astrololo-link, key: LINK_KEY_PRESENTATION_LOGIC } + - name: LINK_ENCRYPTION_REQUIRED + value: "true" + # Za Ingressem bezpośrednim rozmówcą jest pod Traefika. Bez tego limit + # liczyłby WSZYSTKICH do jednego wiadra i pierwsza osoba, która go + # wyklika, odcięłaby pozostałe. + - name: TRUST_PROXY + value: "true" + # Niższy niż w pełnej aplikacji: demo bywa udostępniane szerzej, + # a każde zapytanie sięga do treści baz. + - name: RATE_LIMIT_PER_MIN + value: "60" + resources: + requests: { cpu: "50m", memory: "96Mi" } + limits: { cpu: "300m", memory: "256Mi" } +--- +apiVersion: v1 +kind: Service +metadata: + name: astroklient + namespace: astrololo +spec: + # ClusterIP — wejście z zewnątrz wyłącznie przez Ingress po https, tak samo + # jak prezentacja. Druga, nieszyfrowana droga byłaby obejściem PRE-16. + type: ClusterIP + selector: { app: astroklient } + ports: [{ port: 8005, targetPort: 8005 }] diff --git a/astrololo/image-updater.yaml b/astrololo/image-updater.yaml index 5eb4ce5..689dd1c 100644 --- a/astrololo/image-updater.yaml +++ b/astrololo/image-updater.yaml @@ -34,6 +34,10 @@ spec: imageName: gitea.czernobog.pl/gitea/astrololo-presentation - alias: render imageName: gitea.czernobog.pl/gitea/astrololo-render + # Wersja demo (PRE-28). Obraz, którego nie ma na tej liście, NIGDY się nie + # podbije, choćby CI go budowało — tak przez chwilę wisiał render na :latest. + - alias: astroklient + imageName: gitea.czernobog.pl/gitea/astrololo-astroklient commonUpdateSettings: updateStrategy: newest-build writeBackConfig: diff --git a/astrololo/kustomization.yaml b/astrololo/kustomization.yaml index f376d8d..63ed861 100644 --- a/astrololo/kustomization.yaml +++ b/astrololo/kustomization.yaml @@ -6,6 +6,7 @@ resources: - data.yaml - logic.yaml - presentation.yaml + - astroklient.yaml # wersja demo (PRE-28) — sekret astrololo-demo POZA repo - render.yaml # składanie raportu PDF (PRE-24), osobny obraz z TeX Live - tls.yaml # certyfikat z własnego CA (wymaga cert-managera) - ingress.yaml # wejście po https + przekierowanie z http @@ -16,5 +17,7 @@ images: newTag: ee3c515d - name: gitea.czernobog.pl/gitea/astrololo-render newTag: latest + - name: gitea.czernobog.pl/gitea/astrololo-astroklient + newTag: latest - name: gitea.czernobog.pl/gitea/astrololo-presentation newTag: ee3c515d -- 2.52.0 From e52284c88f1d52a231be6a9d22b429e9d66ac392 Mon Sep 17 00:00:00 2001 From: migatu Date: Mon, 17 Aug 2026 18:59:20 +0200 Subject: [PATCH 2/4] =?UTF-8?q?feat(astroklient):=20w=C5=82asna=20warstwa?= =?UTF-8?q?=20danych=20i=20pule=20per=20konto=20(PRE-29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zmiana wobec pierwszej wersji: demo NIE pracuje już na produkcyjnej warstwie danych. Ma własną logikę i własne dane, na osobnym udziale astrololo-demo, pustym na starcie. Oryginalne bazy są dla demo nieosiągalne — nie przez uprawnienia, tylko dlatego, że nie ma do nich drogi. DLACZEGO OSOBNA JEST TEŻ WARSTWA LOGICZNA. Zna ona JEDEN adres warstwy danych, więc astroklient korzystający z produkcyjnej logiki i tak trafiłby na produkcyjne bazy. Izolacja musi sięgnąć obu warstw naraz, inaczej nie ma jej wcale. Jedyną różnicą logic-demo wobec produkcyjnej jest DATA_URL — i to jest cała izolacja, więc wpisanie tam „logic" cofnęłoby ją jednym słowem. Stąd komentarz przy tej linii i sąsiedztwo obu plików. PULE PER KONTO. Każde konto demo dostaje własny podkatalog na tym udziale, niewidoczny dla pozostałych — w liście plików i w wynikach wyszukiwania. Konta są listą `login:sekret` w sekrecie, bo jedno wspólne oznaczałoby wspólną pulę, czyli klientów oglądających nawzajem swoje wgrania. Ten sam OBRAZ co produkcja dla data i logic — różni je wyłącznie konfiguracja. Osobny obraz to drugi kod do utrzymania i pewność, że kiedyś się rozjadą. Logika demo nie dostaje kluczy do modeli językowych: astroklient nie umie o nie prosić, więc nie ma powodu, żeby leżały w tym podzie. Runbook opisuje IMPORT PULI KLIENTA do pełnej aplikacji — sedno całego układu, bo klient przechodzący na pełną wersję nie może stracić wgrań. Jego pula to jeden katalog: sprawdzenie kolizji nazw, kopiowanie z -n (nigdy nadpisania bazy produkcyjnej), bez pliku stanu (produkcja ma własny), a na końcu świadome włączenie w zakładce Pliki. Nie włączają się same, bo przeniesienie jest czynnością techniczną, a decyzja o użyciu należy do właściciela. Co-Authored-By: Claude Opus 5 --- astrololo/README-astroklient.md | 179 +++++++++++++++++++++++-------- astrololo/README.md | 7 +- astrololo/astroklient-stack.yaml | 122 +++++++++++++++++++++ astrololo/astroklient.yaml | 27 +++-- astrololo/kustomization.yaml | 1 + 5 files changed, 280 insertions(+), 56 deletions(-) create mode 100644 astrololo/astroklient-stack.yaml diff --git a/astrololo/README-astroklient.md b/astrololo/README-astroklient.md index 801c50c..9ce7e20 100644 --- a/astrololo/README-astroklient.md +++ b/astrololo/README-astroklient.md @@ -1,86 +1,177 @@ -# astroklient — wdrożenie wersji demo (PRE-28) +# astroklient — wdrożenie wersji demo (PRE-28/29) Osobna usługa o dwóch funkcjach: **dodanie pliku bazy** i **zapytanie o -interpretację urodzeniową**. Opis samej aplikacji: `services/astroklient/README.md` +interpretację urodzeniową**. Opis aplikacji: `services/astroklient/README.md` w repo aplikacji. --- -## ⚠️ Przeczytaj, zanim komuś dasz adres +## Jak to jest odizolowane -Demo pracuje na **produkcyjnej warstwie danych**. To była świadoma decyzja, ale -niesie dwie konsekwencje, o których trzeba pamiętać za każdym razem: +``` +astroklient → logic-demo → data-demo → /mnt/Tank1/astrololo-demo + └── klientA/ ← pula konta + └── klientB/ ← pula konta +``` -* **kto ma dostęp do demo, czyta Twoje oryginalne bazy interpretacyjne** — czyli - rdzeń produktu, którego pilnują LOG-32, DAN-25 i PRE-27, -* **pliki wgrane przez demo trafiają do produkcyjnego zbioru** i od razu biorą - udział w wyszukiwaniu, także w pełnej aplikacji. +**Oryginalne bazy są dla demo nieosiągalne.** Nie chodzi o uprawnienia: demo ma +własną warstwę danych, pracującą na osobnym udziale, pustym na starcie. -Jeśli demo ma trafić do kogoś spoza kręgu zaufania, właściwą odpowiedzią jest -osobna warstwa danych z pustym udziałem — **nie jest to dziś zrobione**. +Dlaczego osobna jest też **warstwa logiczna**: zna ona jeden adres warstwy danych, +więc astroklient korzystający z produkcyjnej logiki i tak trafiłby na produkcyjne +bazy. Izolacja musi sięgnąć obu warstw naraz, inaczej nie ma jej wcale. + +**Każde konto ma własną pulę** — swój podkatalog na tym udziale. Konta nie widzą +swoich plików nawzajem ani w liście, ani w wynikach wyszukiwania. Pula bierze się +z **loginu zalogowanej osoby**, nigdy z pola formularza. --- -## Krok 1 — sekret z hasłem demo +## Krok 1 — udział `astrololo-demo` na TrueNAS -Osobny sekret, nie `astrololo-auth`. Dzięki temu demo odcina się **jedną komendą**, -bez ruszania kont głównej aplikacji i bez zmiany hasła komukolwiek. +Ta sama procedura co przy `astrololo-state`, więc jeśli tamten działa, ten też +zadziała. Po SSH na NAS: ```bash -read -rs -p "Hasło do demo (DEMO_PASSWORD): " DEMO; echo +sudo zfs create Tank1/astrololo-demo # albo: sudo mkdir -p /mnt/Tank1/astrololo-demo +``` + +```bash +midclt call sharing.nfs.query '[["path","=","/mnt/Tank1/astrololo-demo"]]' \ + | python3 -m json.tool +``` + +**Pusta lista `[]`** — twórz: + +```bash +midclt call sharing.nfs.create '{ + "path": "/mnt/Tank1/astrololo-demo", + "comment": "astrololo — pule kont wersji demo (PRE-29)", + "hosts": ["192.168.1.73", "192.168.1.80", "192.168.1.81"], + "enabled": true, + "ro": false, + "mapall_user": "root", + "mapall_group": "root" +}' +``` + +**Coś zwróciło** — weź `id` i użyj `sharing.nfs.update ` z tą samą treścią. + +```bash +midclt call service.restart nfs +sudo exportfs -v | grep astrololo-demo +``` + +Musi tam być `rw`. Sprawdź jeszcze zapis z węzła — to jest ten test, którego +zabrakło przy poprzednim udziale: + +```bash +ssh 'sudo mkdir -p /mnt/t && sudo mount -t nfs 192.168.1.34:/mnt/Tank1/astrololo-demo /mnt/t \ + && sudo touch /mnt/t/proba && echo ZAPIS-OK || echo ZAPIS-NIE; sudo rm -f /mnt/t/proba; sudo umount /mnt/t' +``` + +--- + +## Krok 2 — konta demo + +Każde konto to osobna pula, więc **rozdajesz konta, nie jedno hasło**. + +Hasła najlepiej jako hash — wtedy nie leżą nigdzie jawnie (skrypt jest w repo +aplikacji, `services/presentation/scripts/make_user.py`): + +```bash +python scripts/make_user.py klientA # wypisze: scrypt$… +python scripts/make_user.py klientB +``` + +```bash +kubectl -n astrololo create secret generic astrololo-demo \ + --from-literal=DEMO_USERS='klientA:scrypt$…,klientB:scrypt$…' +``` + +### Dodanie konta później + +```bash +STARE=$(kubectl -n astrololo get secret astrololo-demo -o jsonpath='{.data.DEMO_USERS}' | base64 -d) kubectl -n astrololo create secret generic astrololo-demo \ - --from-literal=DEMO_PASSWORD="$DEMO" + --from-literal=DEMO_USERS="${STARE},klientC:scrypt\$…" \ + --dry-run=client -o yaml | kubectl apply -f - -unset DEMO +kubectl -n astrololo rollout restart deploy/astroklient ``` -Login to `demo` (zmienny przez `DEMO_USER` w `astroklient.yaml`). +### Odebranie dostępu -Hasło może być też hashem `scrypt$…` — wtedy nie leży nigdzie jawnie: - -```bash -cd services/presentation && python scripts/make_user.py demo # w repo aplikacji -``` +Usuń wpis z `DEMO_USERS` tą samą drogą. **Pula zostaje na udziale** — pliki +klienta nie znikają, tylko przestaje być komu je pokazywać. --- -## Krok 2 — wdrożenie +## Krok 3 — wdrożenie ```bash kubectl apply -k astrololo -kubectl -n astrololo rollout status deploy/astroklient +kubectl -n astrololo rollout status deploy/data-demo deploy/logic-demo deploy/astroklient ``` -Image-updater ma astroklienta na liście, więc kolejne obrazy podbiją się same. - ---- - -## Krok 3 — wejście z zewnątrz - -Usługa jest `ClusterIP`; z zewnątrz wchodzi się **wyłącznie przez Ingress po -https**, tak samo jak do prezentacji. Dopisz regułę do `ingress.yaml` — osobny -host albo ścieżka, zależnie od tego, jak chcesz demo udostępniać. - -Na czas sprawdzenia wystarczy tunel: +Sprawdzenie na czas jednej sesji, bez wystawiania na świat: ```bash kubectl -n astrololo port-forward deploy/astroklient 8005:8005 ``` -i `http://localhost:8005` — login `demo`, hasło z kroku 1. +Wejście z zewnątrz wymaga reguły w `ingress.yaml` — osobny host albo ścieżka. +**Celowo nie zakładam tego za Ciebie**: to decyzja, pod jakim adresem świat +zobaczy demo. --- -## Odcięcie demo +## Import puli klienta do pełnej aplikacji + +Sedno całego układu: klient, który przechodzi na pełną wersję, **nie traci +dotychczasowych wgrań**. Jego pula to jeden katalog. + +**1. Zobacz, co tam jest** (na NAS): ```bash -kubectl -n astrololo delete secret astrololo-demo -kubectl -n astrololo rollout restart deploy/astroklient +LOGIN=klientA +sudo ls -la /mnt/Tank1/astrololo-demo/$LOGIN/ ``` -> Uwaga: **pod bez sekretu nie wstanie** i to jest zachowanie zamierzone. -> Alternatywnie `kubectl -n astrololo scale deploy/astroklient --replicas=0`, -> jeśli chcesz tylko wyłączyć, zachowując konfigurację. +**2. Sprawdź kolizje nazw** z bazami produkcyjnymi: -Konta głównej aplikacji pozostają nietknięte w obu przypadkach. +```bash +comm -12 \ + <(cd /mnt/Tank1/astrololo-demo/$LOGIN && ls *.xlsx 2>/dev/null | sort) \ + <(cd /mnt/Tank1/astrololo && ls *.xlsx 2>/dev/null | sort) +``` + +Pusto = brak kolizji. Cokolwiek się wypisze, przenieś ręcznie pod inną nazwą — +**nie nadpisuj bazy produkcyjnej**. + +**3. Skopiuj** (`-n` = nie nadpisuj niczego, co już jest): + +```bash +sudo cp -n /mnt/Tank1/astrololo-demo/$LOGIN/*.xlsx /mnt/Tank1/astrololo/ +``` + +> Kopiujemy **tylko pliki `.xlsx`**. Plik `.files-state.json` zostaje — opisuje +> stan wewnątrz puli demo i w produkcji nie ma sensu; produkcja ma własny. + +**4. Włącz je w pełnej aplikacji**: zakładka **Pliki**, nowe bazy pojawią się jako +„gotowa, odstawiona". Klikasz przełącznik przy tych, które mają wejść do użytku. + +To, że nie włączają się same, jest zamierzone: przeniesienie plików jest czynnością +techniczną, a decyzja, które bazy biorą udział w interpretacji, należy do Ciebie. + +--- + +## Odcięcie całego demo + +```bash +kubectl -n astrololo scale deploy/astroklient --replicas=0 +``` + +Pule i dane zostają. Skasowanie sekretu `astrololo-demo` zatrzyma pod (nie wstanie +bez niego) i to też jest zachowanie zamierzone. diff --git a/astrololo/README.md b/astrololo/README.md index dda4149..778b31c 100644 --- a/astrololo/README.md +++ b/astrololo/README.md @@ -33,9 +33,10 @@ NFS. Co zostaje z zabezpieczeń i jak to wdrożyć — w runbooku. Osobna usługa o dwóch funkcjach. Runbook: **[README-astroklient.md](README-astroklient.md)**. -⚠️ Pracuje na **produkcyjnej warstwie danych** — kto ma dostęp do demo, czyta -oryginalne bazy. Konto jest osobne (`astrololo-demo`), więc odcina się bez ruszania -kont głównej aplikacji. +Ma **własną warstwę logiczną i własną warstwę danych** na osobnym udziale +`astrololo-demo` — oryginalne bazy są dla demo nieosiągalne. Każde konto demo ma +własną, niewidoczną dla pozostałych pulę plików, a jego pulę da się później +przenieść do pełnej aplikacji jako jeden katalog. ## ⚠️ Sekret `astrololo-auth` — utwórz PRZED wdrożeniem diff --git a/astrololo/astroklient-stack.yaml b/astrololo/astroklient-stack.yaml new file mode 100644 index 0000000..66d350a --- /dev/null +++ b/astrololo/astroklient-stack.yaml @@ -0,0 +1,122 @@ +# Warstwa danych i logiki WYŁĄCZNIE dla wersji demo (PRE-29). +# +# DLACZEGO OSOBNY KOMPLET, A NIE WSPÓŁDZIELONY. Warstwa logiczna zna JEDEN adres +# warstwy danych, więc astroklient korzystający z produkcyjnej logiki i tak trafiłby +# na produkcyjne bazy. Izolacja demo musi więc sięgnąć obu warstw naraz, inaczej +# nie ma jej wcale. +# +# Udział `astrololo-demo` jest PUSTY na starcie i nigdy nie zawiera oryginalnych +# baz. Każde konto demo dostaje w nim własny podkatalog (pulę) — patrz PRE-29. +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: data-demo + namespace: astrololo +spec: + replicas: 1 + selector: + matchLabels: { app: data-demo } + template: + metadata: + labels: { app: data-demo } + spec: + containers: + - name: data + # TEN SAM obraz co produkcja — różni się wyłącznie udziałem, na którym + # pracuje. Osobny obraz oznaczałby drugi kod do utrzymania i pewność, + # że kiedyś się rozjadą. + image: gitea.czernobog.pl/gitea/astrololo-data:latest + ports: [{ containerPort: 8002 }] + env: + - name: DATA_PROVIDER + value: "excel" + - name: EXCEL_DIR + value: "/app/data_files" + - name: CACHE_DIR + value: "/app/.cache" + - name: INTERNAL_TOKEN + valueFrom: + secretKeyRef: { name: astrololo-auth, key: INTERNAL_TOKEN } + - name: LINK_KEY_LOGIC_DATA + valueFrom: + secretKeyRef: { name: astrololo-link, key: LINK_KEY_LOGIC_DATA } + - name: LINK_ENCRYPTION_REQUIRED + value: "true" + volumeMounts: + - name: cache + mountPath: /app/.cache + - name: demo + mountPath: /app/data_files + resources: + requests: { cpu: "100m", memory: "256Mi" } + limits: { cpu: "500m", memory: "512Mi" } + volumes: + - name: cache + emptyDir: {} + - name: demo + nfs: + server: 192.168.1.34 + # OSOBNY udział, pusty na starcie. NIE /mnt/Tank1/astrololo — + # to jest cała istota izolacji demo. + path: /mnt/Tank1/astrololo-demo +--- +apiVersion: v1 +kind: Service +metadata: + name: data-demo + namespace: astrololo +spec: + type: ClusterIP + selector: { app: data-demo } + ports: [{ port: 8002, targetPort: 8002 }] +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: logic-demo + namespace: astrololo +spec: + replicas: 1 + selector: + matchLabels: { app: logic-demo } + template: + metadata: + labels: { app: logic-demo } + spec: + containers: + - name: logic + image: gitea.czernobog.pl/gitea/astrololo-logic:latest + ports: [{ containerPort: 8001 }] + env: + # JEDYNA różnica wobec produkcyjnej logiki — i zarazem cała izolacja. + - name: DATA_URL + value: "http://data-demo:8002" + - name: EPHEMERIS_ENGINE + value: "own" + - name: INTERNAL_TOKEN + valueFrom: + secretKeyRef: { name: astrololo-auth, key: INTERNAL_TOKEN } + - name: LINK_KEY_PRESENTATION_LOGIC + valueFrom: + secretKeyRef: { name: astrololo-link, key: LINK_KEY_PRESENTATION_LOGIC } + - name: LINK_KEY_LOGIC_DATA + valueFrom: + secretKeyRef: { name: astrololo-link, key: LINK_KEY_LOGIC_DATA } + - name: LINK_ENCRYPTION_REQUIRED + value: "true" + # Bez kluczy do modeli językowych. Astroklient nie umie o nie prosić, + # więc ich tu nie ma — czego nie ma w podzie, tego nie wyniesie. + resources: + requests: { cpu: "100m", memory: "128Mi" } + limits: { cpu: "500m", memory: "512Mi" } +--- +apiVersion: v1 +kind: Service +metadata: + name: logic-demo + namespace: astrololo +spec: + type: ClusterIP + selector: { app: logic-demo } + ports: [{ port: 8001, targetPort: 8001 }] diff --git a/astrololo/astroklient.yaml b/astrololo/astroklient.yaml index e6a7003..6af55b1 100644 --- a/astrololo/astroklient.yaml +++ b/astrololo/astroklient.yaml @@ -3,10 +3,14 @@ # Osobna usługa o DWÓCH funkcjach: dodanie pliku bazy i zapytanie o interpretację # urodzeniową. Pozostałe funkcje nie są tu ukryte — nie ma ich w obrazie. # -# ⚠️ PRACUJE NA PRODUKCYJNEJ WARSTWIE DANYCH (świadoma decyzja właściciela). -# Kto ma dostęp do demo, czyta oryginalne bazy interpretacyjne, a pliki przez nie -# wgrane trafiają do produkcyjnego zbioru. Dlatego konto jest OSOBNE: demo odcina -# się skasowaniem sekretu astrololo-demo, bez ruszania kont głównej aplikacji. +# IZOLACJA (PRE-29): astroklient ma WŁASNĄ warstwę logiczną i WŁASNĄ warstwę +# danych (astroklient-stack.yaml), pracujące na osobnym, pustym na starcie +# udziale. Oryginalne bazy interpretacyjne są dla demo NIEOSIĄGALNE. +# +# Wewnątrz demo każde konto ma własną pulę plików — swój podkatalog na tym +# udziale — niewidoczną dla pozostałych kont. Dzięki temu demo można rozdawać +# szeroko, a pliki jednego klienta da się później przenieść do pełnej aplikacji +# jako jeden katalog (patrz README-astroklient.md). apiVersion: apps/v1 kind: Deployment metadata: @@ -25,15 +29,20 @@ spec: image: gitea.czernobog.pl/gitea/astrololo-astroklient:latest ports: [{ containerPort: 8005 }] env: + # WŁASNA warstwa logiczna, wskazująca na WŁASNĄ warstwę danych. + # Wpisanie tu produkcyjnego `logic` cofnęłoby całą izolację demo + # jednym słowem — dlatego stoi to tuż obok siebie w jednym pliku. - name: LOGIC_URL - value: "http://logic:8001" + value: "http://logic-demo:8001" # Konto demo — WŁASNE, nie astrololo-auth. Sekret tworzony POZA repo # (jak pozostałe), patrz README-astroklient.md. - - name: DEMO_USER - value: "demo" - - name: DEMO_PASSWORD + # KONTA DEMO — lista `login:sekret` po przecinku. Każde konto ma + # WŁASNĄ, niewidoczną dla pozostałych pulę baz (PRE-29), więc jedno + # wspólne konto oznaczałoby klientów oglądających swoje wgrania + # nawzajem. Sekrety najlepiej jako hash scrypt. + - name: DEMO_USERS valueFrom: - secretKeyRef: { name: astrololo-demo, key: DEMO_PASSWORD } + secretKeyRef: { name: astrololo-demo, key: DEMO_USERS } # Token międzywarstwowy i klucz łącza — TE SAME co prezentacja: # demo nie jest furtką omijającą ochronę warstwy logicznej. - name: INTERNAL_TOKEN diff --git a/astrololo/kustomization.yaml b/astrololo/kustomization.yaml index 63ed861..314c821 100644 --- a/astrololo/kustomization.yaml +++ b/astrololo/kustomization.yaml @@ -6,6 +6,7 @@ resources: - data.yaml - logic.yaml - presentation.yaml + - astroklient-stack.yaml # OSOBNA warstwa danych i logiki dla demo (PRE-29) - astroklient.yaml # wersja demo (PRE-28) — sekret astrololo-demo POZA repo - render.yaml # składanie raportu PDF (PRE-24), osobny obraz z TeX Live - tls.yaml # certyfikat z własnego CA (wymaga cert-managera) -- 2.52.0 From a9ff6e1f68fe3a738a5bee3f32ae0f0ecd817869 Mon Sep 17 00:00:00 2001 From: migatu Date: Thu, 20 Aug 2026 23:36:57 +0200 Subject: [PATCH 3/4] =?UTF-8?q?refactor:=20astroklient=20=E2=86=92=20astro?= =?UTF-8?q?klient-demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nazwa `astroklient` zostaje zarezerwowana dla przyszłej wersji produkcyjnej; obecna, demonstracyjna nazywa się od teraz `astroklient-demo`. Zmiana obejmuje nazwy plików (astroklient-demo.yaml, astroklient-demo-stack.yaml, README-astroklient-demo.md), Deployment i Service, etykiety selektorów, obraz w rejestrze, alias w image-updaterze, wpisy w kustomization i odsyłacze w README. `data-demo` i `logic-demo` zostają bez zmian — nie niosły starej nazwy. Sprawdzone: `kubectl kustomize astrololo` składa komplet 27 zasobów, obraz to astrololo-astroklient-demo, żadnego zdublowanego przyrostka ani gołego `astroklient` nie zostało. Co-Authored-By: Claude Opus 5 --- ...roklient.md => README-astroklient-demo.md} | 16 ++++++------- astrololo/README.md | 4 ++-- ...stack.yaml => astroklient-demo-stack.yaml} | 2 +- ...astroklient.yaml => astroklient-demo.yaml} | 24 +++++++++---------- astrololo/image-updater.yaml | 4 ++-- astrololo/kustomization.yaml | 6 ++--- 6 files changed, 28 insertions(+), 28 deletions(-) rename astrololo/{README-astroklient.md => README-astroklient-demo.md} (91%) rename astrololo/{astroklient-stack.yaml => astroklient-demo-stack.yaml} (97%) rename astrololo/{astroklient.yaml => astroklient-demo.yaml} (82%) diff --git a/astrololo/README-astroklient.md b/astrololo/README-astroklient-demo.md similarity index 91% rename from astrololo/README-astroklient.md rename to astrololo/README-astroklient-demo.md index 9ce7e20..1ffbfed 100644 --- a/astrololo/README-astroklient.md +++ b/astrololo/README-astroklient-demo.md @@ -1,7 +1,7 @@ -# astroklient — wdrożenie wersji demo (PRE-28/29) +# astroklient-demo — wdrożenie wersji demo (PRE-28/29) Osobna usługa o dwóch funkcjach: **dodanie pliku bazy** i **zapytanie o -interpretację urodzeniową**. Opis aplikacji: `services/astroklient/README.md` +interpretację urodzeniową**. Opis aplikacji: `services/astroklient-demo/README.md` w repo aplikacji. --- @@ -9,7 +9,7 @@ w repo aplikacji. ## Jak to jest odizolowane ``` -astroklient → logic-demo → data-demo → /mnt/Tank1/astrololo-demo +astroklient-demo → logic-demo → data-demo → /mnt/Tank1/astrololo-demo └── klientA/ ← pula konta └── klientB/ ← pula konta ``` @@ -18,7 +18,7 @@ astroklient → logic-demo → data-demo → /mnt/Tank1/astrololo-demo własną warstwę danych, pracującą na osobnym udziale, pustym na starcie. Dlaczego osobna jest też **warstwa logiczna**: zna ona jeden adres warstwy danych, -więc astroklient korzystający z produkcyjnej logiki i tak trafiłby na produkcyjne +więc astroklient-demo korzystający z produkcyjnej logiki i tak trafiłby na produkcyjne bazy. Izolacja musi sięgnąć obu warstw naraz, inaczej nie ma jej wcale. **Każde konto ma własną pulę** — swój podkatalog na tym udziale. Konta nie widzą @@ -98,7 +98,7 @@ kubectl -n astrololo create secret generic astrololo-demo \ --from-literal=DEMO_USERS="${STARE},klientC:scrypt\$…" \ --dry-run=client -o yaml | kubectl apply -f - -kubectl -n astrololo rollout restart deploy/astroklient +kubectl -n astrololo rollout restart deploy/astroklient-demo ``` ### Odebranie dostępu @@ -112,13 +112,13 @@ klienta nie znikają, tylko przestaje być komu je pokazywać. ```bash kubectl apply -k astrololo -kubectl -n astrololo rollout status deploy/data-demo deploy/logic-demo deploy/astroklient +kubectl -n astrololo rollout status deploy/data-demo deploy/logic-demo deploy/astroklient-demo ``` Sprawdzenie na czas jednej sesji, bez wystawiania na świat: ```bash -kubectl -n astrololo port-forward deploy/astroklient 8005:8005 +kubectl -n astrololo port-forward deploy/astroklient-demo 8005:8005 ``` Wejście z zewnątrz wymaga reguły w `ingress.yaml` — osobny host albo ścieżka. @@ -170,7 +170,7 @@ techniczną, a decyzja, które bazy biorą udział w interpretacji, należy do C ## Odcięcie całego demo ```bash -kubectl -n astrololo scale deploy/astroklient --replicas=0 +kubectl -n astrololo scale deploy/astroklient-demo --replicas=0 ``` Pule i dane zostają. Skasowanie sekretu `astrololo-demo` zatrzyma pod (nie wstanie diff --git a/astrololo/README.md b/astrololo/README.md index 778b31c..40dbb62 100644 --- a/astrololo/README.md +++ b/astrololo/README.md @@ -29,9 +29,9 @@ Runbook: **[README-pliki.md](README-pliki.md)**. Ekran „Pliki" wymaga zapisu d udziału z bazami, więc znosi gwarancję z DAN-25, że baz nie da się zmienić przez NFS. Co zostaje z zabezpieczeń i jak to wdrożyć — w runbooku. -## astroklient — wersja demo (PRE-28) +## astroklient-demo — wersja demo (PRE-28) -Osobna usługa o dwóch funkcjach. Runbook: **[README-astroklient.md](README-astroklient.md)**. +Osobna usługa o dwóch funkcjach. Runbook: **[README-astroklient-demo.md](README-astroklient-demo.md)**. Ma **własną warstwę logiczną i własną warstwę danych** na osobnym udziale `astrololo-demo` — oryginalne bazy są dla demo nieosiągalne. Każde konto demo ma diff --git a/astrololo/astroklient-stack.yaml b/astrololo/astroklient-demo-stack.yaml similarity index 97% rename from astrololo/astroklient-stack.yaml rename to astrololo/astroklient-demo-stack.yaml index 66d350a..baad6a6 100644 --- a/astrololo/astroklient-stack.yaml +++ b/astrololo/astroklient-demo-stack.yaml @@ -1,7 +1,7 @@ # Warstwa danych i logiki WYŁĄCZNIE dla wersji demo (PRE-29). # # DLACZEGO OSOBNY KOMPLET, A NIE WSPÓŁDZIELONY. Warstwa logiczna zna JEDEN adres -# warstwy danych, więc astroklient korzystający z produkcyjnej logiki i tak trafiłby +# warstwy danych, więc astroklient-demo korzystający z produkcyjnej logiki i tak trafiłby # na produkcyjne bazy. Izolacja demo musi więc sięgnąć obu warstw naraz, inaczej # nie ma jej wcale. # diff --git a/astrololo/astroklient.yaml b/astrololo/astroklient-demo.yaml similarity index 82% rename from astrololo/astroklient.yaml rename to astrololo/astroklient-demo.yaml index 6af55b1..f73d420 100644 --- a/astrololo/astroklient.yaml +++ b/astrololo/astroklient-demo.yaml @@ -1,32 +1,32 @@ -# astroklient — wersja demonstracyjna (PRE-28). +# astroklient-demo — wersja demonstracyjna (PRE-28). # # Osobna usługa o DWÓCH funkcjach: dodanie pliku bazy i zapytanie o interpretację # urodzeniową. Pozostałe funkcje nie są tu ukryte — nie ma ich w obrazie. # -# IZOLACJA (PRE-29): astroklient ma WŁASNĄ warstwę logiczną i WŁASNĄ warstwę -# danych (astroklient-stack.yaml), pracujące na osobnym, pustym na starcie +# IZOLACJA (PRE-29): astroklient-demo ma WŁASNĄ warstwę logiczną i WŁASNĄ warstwę +# danych (astroklient-demo-stack.yaml), pracujące na osobnym, pustym na starcie # udziale. Oryginalne bazy interpretacyjne są dla demo NIEOSIĄGALNE. # # Wewnątrz demo każde konto ma własną pulę plików — swój podkatalog na tym # udziale — niewidoczną dla pozostałych kont. Dzięki temu demo można rozdawać # szeroko, a pliki jednego klienta da się później przenieść do pełnej aplikacji -# jako jeden katalog (patrz README-astroklient.md). +# jako jeden katalog (patrz README-astroklient-demo.md). apiVersion: apps/v1 kind: Deployment metadata: - name: astroklient + name: astroklient-demo namespace: astrololo spec: replicas: 1 selector: - matchLabels: { app: astroklient } + matchLabels: { app: astroklient-demo } template: metadata: - labels: { app: astroklient } + labels: { app: astroklient-demo } spec: containers: - - name: astroklient - image: gitea.czernobog.pl/gitea/astrololo-astroklient:latest + - name: astroklient-demo + image: gitea.czernobog.pl/gitea/astrololo-astroklient-demo:latest ports: [{ containerPort: 8005 }] env: # WŁASNA warstwa logiczna, wskazująca na WŁASNĄ warstwę danych. @@ -35,7 +35,7 @@ spec: - name: LOGIC_URL value: "http://logic-demo:8001" # Konto demo — WŁASNE, nie astrololo-auth. Sekret tworzony POZA repo - # (jak pozostałe), patrz README-astroklient.md. + # (jak pozostałe), patrz README-astroklient-demo.md. # KONTA DEMO — lista `login:sekret` po przecinku. Każde konto ma # WŁASNĄ, niewidoczną dla pozostałych pulę baz (PRE-29), więc jedno # wspólne konto oznaczałoby klientów oglądających swoje wgrania @@ -69,11 +69,11 @@ spec: apiVersion: v1 kind: Service metadata: - name: astroklient + name: astroklient-demo namespace: astrololo spec: # ClusterIP — wejście z zewnątrz wyłącznie przez Ingress po https, tak samo # jak prezentacja. Druga, nieszyfrowana droga byłaby obejściem PRE-16. type: ClusterIP - selector: { app: astroklient } + selector: { app: astroklient-demo } ports: [{ port: 8005, targetPort: 8005 }] diff --git a/astrololo/image-updater.yaml b/astrololo/image-updater.yaml index 689dd1c..87f2f46 100644 --- a/astrololo/image-updater.yaml +++ b/astrololo/image-updater.yaml @@ -36,8 +36,8 @@ spec: imageName: gitea.czernobog.pl/gitea/astrololo-render # Wersja demo (PRE-28). Obraz, którego nie ma na tej liście, NIGDY się nie # podbije, choćby CI go budowało — tak przez chwilę wisiał render na :latest. - - alias: astroklient - imageName: gitea.czernobog.pl/gitea/astrololo-astroklient + - alias: astroklient-demo + imageName: gitea.czernobog.pl/gitea/astrololo-astroklient-demo commonUpdateSettings: updateStrategy: newest-build writeBackConfig: diff --git a/astrololo/kustomization.yaml b/astrololo/kustomization.yaml index 314c821..2c27b3a 100644 --- a/astrololo/kustomization.yaml +++ b/astrololo/kustomization.yaml @@ -6,8 +6,8 @@ resources: - data.yaml - logic.yaml - presentation.yaml - - astroklient-stack.yaml # OSOBNA warstwa danych i logiki dla demo (PRE-29) - - astroklient.yaml # wersja demo (PRE-28) — sekret astrololo-demo POZA repo + - astroklient-demo-stack.yaml # OSOBNA warstwa danych i logiki dla demo (PRE-29) + - astroklient-demo.yaml # wersja demo (PRE-28) — sekret astrololo-demo POZA repo - render.yaml # składanie raportu PDF (PRE-24), osobny obraz z TeX Live - tls.yaml # certyfikat z własnego CA (wymaga cert-managera) - ingress.yaml # wejście po https + przekierowanie z http @@ -18,7 +18,7 @@ images: newTag: ee3c515d - name: gitea.czernobog.pl/gitea/astrololo-render newTag: latest - - name: gitea.czernobog.pl/gitea/astrololo-astroklient + - name: gitea.czernobog.pl/gitea/astrololo-astroklient-demo newTag: latest - name: gitea.czernobog.pl/gitea/astrololo-presentation newTag: ee3c515d -- 2.52.0 From 7e0a51878e673d30191c1e9204a4f779eeb9f1e8 Mon Sep 17 00:00:00 2001 From: migatu Date: Fri, 21 Aug 2026 00:21:52 +0200 Subject: [PATCH 4/4] =?UTF-8?q?feat(astroklient-demo):=20w=C5=82asny=20klu?= =?UTF-8?q?cz=20podpisu=20sesji=20(LOG-34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SESSION_SECRET w sekrecie astrololo-demo — WŁASNY, nie ten z pełnej aplikacji: demo i produkcja nie mają powodu uznawać nawzajem swoich sesji. W runbooku zapisana różnica wobec pełnej wersji: demo nie ma własnego wolumenu, więc nie ma licznika sesji. Zdalne unieważnienie robi się przez DEMO_USERS — usunięcie konta albo zmiana hasła natychmiast ubija jego otwarte sesje. Co-Authored-By: Claude Opus 5 --- astrololo/README-astroklient-demo.md | 13 ++++++++++++- astrololo/astroklient-demo.yaml | 7 +++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/astrololo/README-astroklient-demo.md b/astrololo/README-astroklient-demo.md index 1ffbfed..b40e095 100644 --- a/astrololo/README-astroklient-demo.md +++ b/astrololo/README-astroklient-demo.md @@ -86,9 +86,20 @@ python scripts/make_user.py klientB ```bash kubectl -n astrololo create secret generic astrololo-demo \ - --from-literal=DEMO_USERS='klientA:scrypt$…,klientB:scrypt$…' + --from-literal=DEMO_USERS='klientA:scrypt$…,klientB:scrypt$…' \ + --from-literal=SESSION_SECRET="$(openssl rand -hex 32)" ``` +`SESSION_SECRET` podpisuje ciasteczka sesji (LOG-34). **Pod bez niego celowo nie +wstanie.** Jest WŁASNY, nie ten z pełnej aplikacji: demo i produkcja nie mają +powodu uznawać nawzajem swoich sesji. + +> **Zdalne unieważnienie w demo działa inaczej niż w pełnej wersji.** Demo nie ma +> własnego wolumenu, więc nie ma gdzie trzymać licznika sesji. Zamiast tego: +> usunięcie konta z `DEMO_USERS` albo zmiana jego hasła **natychmiast ubija jego +> otwarte sesje** — bo odcisk poświadczenia wpisany w ciasteczko przestaje pasować. +> Rotacja `SESSION_SECRET` wylogowuje wszystkich naraz. + ### Dodanie konta później ```bash diff --git a/astrololo/astroklient-demo.yaml b/astrololo/astroklient-demo.yaml index f73d420..419e1d9 100644 --- a/astrololo/astroklient-demo.yaml +++ b/astrololo/astroklient-demo.yaml @@ -53,6 +53,13 @@ spec: secretKeyRef: { name: astrololo-link, key: LINK_KEY_PRESENTATION_LOGIC } - name: LINK_ENCRYPTION_REQUIRED value: "true" + # Klucz podpisu ciasteczek sesji (LOG-34). WYMAGANY — pod bez niego + # celowo nie wstaje. WŁASNY, nie ten z pełnej aplikacji: demo i produkcja + # nie mają powodu uznawać nawzajem swoich sesji, a wspólny klucz + # znaczyłby, że sesja z demo bywa ważna tam, gdzie nie powinna. + - name: SESSION_SECRET + valueFrom: + secretKeyRef: { name: astrololo-demo, key: SESSION_SECRET } # Za Ingressem bezpośrednim rozmówcą jest pod Traefika. Bez tego limit # liczyłby WSZYSTKICH do jednego wiadra i pierwsza osoba, która go # wyklika, odcięłaby pozostałe. -- 2.52.0