feat(astroklient): wdrożenie wersji demonstracyjnej (PRE-28)

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 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 18:39:48 +02:00
parent 3ea509b13a
commit 82c73f6aa5
5 changed files with 171 additions and 0 deletions
+86
View File
@@ -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.
+8
View File
@@ -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
+70
View File
@@ -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 }]
+4
View File
@@ -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:
+3
View File
@@ -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