Files
astrololo/docs/wdrozenie-render-pdf.md
T
gitea f24616d342
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m4s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m57s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 34s
Testy / Kontrola składni wszystkich warstw (push) Successful in 22s
feat(render): raport PDF przez LaTeX jako osobna usluga (PRE-24)
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>
2026-07-24 19:21:49 +02:00

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=true działa fail-closed. Bez klucza pod render nie 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łóż podsumowaniePobierz 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-convert z 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.