Ostatnia z osmiu wskazowek partnerow. Nowa usluga services/render sklada raport:
generuje plik posredni .tex i kompiluje go XeLaTeX-em do PDF.
OSOBNY komponent, nie czesc prezentacji — ta sama zasada co przy izolacji
swissepha (LOG-27). TeX Live wazy setki megabajtow; w obrazie produktu
spowalnialby kazdy build, a tak aktualizuje sie niezaleznie i jego awaria nie
kladzie aplikacji, tylko przycisk „Pobierz PDF".
SZYFROWANIE, o ktore prosiles: lacze prezentacja↔render idzie tak samo jak
pozostale, ale z WLASNYM, TRZECIM kluczem (LINK_KEY_PRESENTATION_RENDER). Osobny,
bo tym laczem plynie CALY raport — dane urodzeniowe i opisy z baz — wiec przejecie
go nie moze otwierac lacza do logiki ani do danych. Fail-closed: bez klucza pod
nie wstaje. Test kopii link_crypto obejmuje teraz cztery uslugi.
Uklad PDF wg prosby: imie i nazwisko -> wprowadzone dane -> RYSUNEK kosmogramu
-> interpretacja natalna -> predykcje okresowe. Test pilnuje kolejnosci.
Dwie rzeczy, ktore wyszly dopiero przy skladaniu tego kawalka:
1. KOSMOGRAM NIE NADAWAL SIE DO PDF. Uzywa zmiennych CSS (var(--line)) i klasy
.glyph, ktorej font podaje styles.css — a samodzielny konwerter SVG→PDF nie zna
naszego arkusza. Wyszlyby czarne kreski BEZ SYMBOLI. Stad wariant „print":
konkretne kolory na bialym tle i font glifow wpisany wprost w rysunek. Przy
okazji zalatwia to etap 4 planu kola (wariant do druku).
2. UCIECZKA ZNAKOW LATEXA byla zepsuta — i zlapal to moj wlasny test. Zamiana
„\” na \textbackslash{} szla w tej samej petli co nawiasy, wiec kolejne
podmiany ucieklyby nawiasy dopiero co wstawione: wychodzilo
\textbackslash\{\}. Poprawka: ukosnik chowany pod znacznik zastepczy i
rozwijany na koncu. To nie kosmetyka — niezauwazony „%” komentuje RESZTE LINII,
wiec zdanie od modelu urywaloby sie w polowie, a PDF powstawalby normalnie,
tylko krotszy. Test na wrogim tekscie sprawdza tez, ze \end{document} ani
\input{} nie wyrwa sie z dokumentu.
Usluga nie zapisuje nic poza katalogiem tymczasowym, ktory sprzata po sobie;
w manifescie readOnlyRootFilesystem + emptyDir na /tmp. /health raportuje
obecnosc xelatex i rsvg-convert, zeby zepsuty obraz bylo widac od razu.
Zweryfikowane na zywo (TestClient uslugi render): zadanie bez szyfrowania
z POPRAWNYM tokenem -> 400; obcy klucz -> 400 i tajny opis nie wraca; wlasciwy
klucz -> zadanie dochodzi do aplikacji, tresci baz NIE MA na kablu, odpowiedz
zaszyfrowana. Manifesty przechodza kubectl apply --dry-run=server na zywym
klastrze.
CZEGO NIE SPRAWDZILEM: samej kompilacji PDF. W tym srodowisku nie ma ani TeX
Live, ani dzialajacego runtime'u kontenerow (docker CLI jest, daemon nie) —
probowalem zbudowac obraz i sie nie dalo. Sprawdzone jest wszystko dookola:
generowanie .tex, ucieczka znakow, szyfrowanie, kontrakt API, samowystarczalnosc
SVG. Pierwsze uruchomienie na klastrze trzeba obejrzec — dlatego PRE-24 zostaje
jako „W trakcie", nie „Zrobione".
Instrukcja wdrozenia: docs/wdrozenie-render-pdf.md (klucz, obraz, merge,
weryfikacja, znane ograniczenia).
Testy: 15 nowych (render) + 14 (lacze i wariant druku w prezentacji).
Calosc: prezentacja 131, logika 265/1 skip, render 15.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5.6 KiB
Wdrożenie usługi render — raport PDF (PRE-24)
Instrukcja krok po kroku dla nowego komponentu. Dotyczy dwóch repozytoriów:
| Repo | Co wnosi |
|---|---|
gitea/astrololo |
usługa services/render, klient w prezentacji, przycisk „Pobierz PDF", wariant kosmogramu do druku |
gitea/deploy |
astrololo/render.yaml, adres i klucz łącza w presentation.yaml |
Dlaczego osobna usługa
TeX Live waży setki megabajtów. W obrazie prezentacji spowalniałby każdy build i deploy, a przy każdej poprawce w CSS trzeba by go ciągnąć od nowa. Osobno: obraz produktu zostaje mały, TeX aktualizuje się niezależnie, a awaria renderu nie kładzie aplikacji — przestaje działać wyłącznie przycisk „Pobierz PDF".
To ta sama zasada, co przy izolacji silnika swisseph (LOG-27).
Krok 1 — klucz łącza (PRZED wdrożeniem)
Usługa dostaje cały raport: dane urodzeniowe i opisy z baz. Łącze jest szyfrowane AES-256-GCM, własnym, trzecim kluczem — przejęcie go nie może otwierać łącza do logiki ani do danych.
Sekret astrololo-link już istnieje (PRE-16); dokładamy do niego trzeci klucz,
zachowując dwa dotychczasowe:
kubectl -n astrololo create secret generic astrololo-link \
--from-literal=LINK_KEY_PRESENTATION_LOGIC="$(kubectl -n astrololo get secret astrololo-link \
-o jsonpath='{.data.LINK_KEY_PRESENTATION_LOGIC}' | base64 -d)" \
--from-literal=LINK_KEY_LOGIC_DATA="$(kubectl -n astrololo get secret astrololo-link \
-o jsonpath='{.data.LINK_KEY_LOGIC_DATA}' | base64 -d)" \
--from-literal=LINK_KEY_PRESENTATION_RENDER="$(openssl rand -hex 32)" \
--dry-run=client -o yaml | kubectl apply -f -
Sprawdzenie — mają być trzy klucze:
kubectl -n astrololo get secret astrololo-link -o jsonpath='{.data}' | tr ',' '\n'
Uwaga:
LINK_ENCRYPTION_REQUIRED=truedziała fail-closed. Bez klucza podrendernie wstanie — i tak ma być. Usługa, która wstała i po cichu nie szyfruje, jest gorsza niż CrashLoop, bo awarii nie widać.
Krok 2 — obraz usługi
Obraz budowany jest osobnym workflow (jak silnik swisseph — nie wchodzi do głównego pipeline'u produktu). Pierwszy build trwa dłużej, bo ciągnie TeX Live.
kubectl -n astrololo get deploy render -o jsonpath='{.spec.template.spec.containers[0].image}'; echo
Pakiety w obrazie dobrane wąsko (nie texlive-full, który ma kilka GB):
| Pakiet | Po co |
|---|---|
texlive-xetex |
silnik XeLaTeX — konieczny, bo raport ma polskie znaki i glify astrologiczne; pdflatex ich nie złoży |
texlive-latex-recommended |
geometry, graphicx |
fonts-dejavu-core |
jeden font na polskie znaki i symbole (♄ ♓ ☉) |
librsvg2-bin |
rsvg-convert — SVG kosmogramu → PDF (LaTeX nie wstawia SVG wprost) |
Dockerfile sprawdza obecność obu narzędzi przy budowie, więc zepsuty obraz nie dojedzie na produkcję niezauważony.
Krok 3 — merge manifestów
tea pr merge --login gitea --repo gitea/deploy <numer>
kubectl -n astrololo rollout status deploy/render deploy/presentation
Wjeżdża naraz: Deployment + Service renderu (ClusterIP — bez Ingressu
i NodePortu, nie ma powodu sięgać do niej z zewnątrz) oraz RENDER_URL
i trzeci klucz w prezentacji.
Krok 4 — sprawdzenie
Narzędzia są na miejscu
/health raportuje obecność xelatex i rsvg-convert, żeby zepsuty obraz
było widać od razu, a nie dopiero przy pierwszym raporcie:
kubectl -n astrololo exec deploy/presentation -- \
python -c "import httpx; print(httpx.get('http://render:8004/health').text)"
Oczekiwane: {"status":"ok","layer":"render","tools":{"xelatex":true,"rsvg-convert":true}}.
Gdy status to degraded — obraz zbudował się bez któregoś narzędzia.
Łącze faktycznie szyfruje
Najmocniejszy test to próba obejścia. Z wnętrza klastra, z poprawnym tokenem, ale bez szyfrowania:
kubectl -n astrololo exec deploy/presentation -- python -c "
import httpx, os
r = httpx.post('http://render:8004/pdf', json={'person':'test'},
headers={'X-Astrololo-Token': os.environ['INTERNAL_TOKEN']})
print(r.status_code, r.text[:80])
"
Oczekiwane: 400 i Łącze międzywarstwowe wymaga szyfrowania. Sam token już
nie wystarcza — o to chodziło.
Raport od końca do końca
W przeglądarce: Skompiluj → wypełnij dane → Złóż podsumowanie → Pobierz PDF. PDF ma zacząć się od imienia i nazwiska, potem wprowadzone dane, rysunek kosmogramu, a po nim interpretacja natalna i predykcje okresowe.
Czego ta wersja nie załatwia
- Kompilacja PDF nie została sprawdzona end-to-end w środowisku, w którym
powstawała — nie było tam ani TeX Live, ani runtime'u kontenerów. Sprawdzone
jest wszystko dookoła: generowanie źródła
.tex(w tym ucieczka znaków specjalnych), szyfrowanie łącza, kontrakt API i samowystarczalność SVG. Pierwsze uruchomienie na klastrze trzeba obejrzeć. - Dzielenie wyrazów jest angielskie — nie wciągamy
polyglossia, żeby nie puchł obraz. Tekst składa się poprawnie, tylko przenoszenie bywa nieoptymalne. - Brak kolejki. Długi raport blokuje jedno połączenie na czas kompilacji (timeout klienta: 180 s). Przy większym ruchu warto dołożyć zadania w tle.
- Glify w tekście od modelu. Kosmogram idzie jako obraz (rysuje go
rsvg-convertz DejaVu), ale gdyby model wplótł symbole w prozę, złoży je XeLaTeX — też z DejaVu. Jeśli któregoś zabraknie, LaTeX zgłasza „Missing character" w logu i nie drukuje znaku; warto zerknąć w log pierwszego raportu.