astrodemo: zmiana nazwy, rebase i domknięcie wycieków (1/5) #79

Merged
gitea merged 6 commits from feat/astrodemo into master 2026-08-26 14:25:29 +00:00
Owner

Pierwszy z pięciu kroków budowy trzech produktów. Zastępuje #74 — tamten PR stoi na nieaktualnym masterze i na starej nazwie, można go zamknąć.

Nazwa astroklient zostaje zwolniona dla warstwy pośredniej, więc dotychczasowe astroklient-demo to teraz astrodemo.

Rebase

Cztery commity demo przeniesione na aktualnego mastera. Konflikt był jeden: rejestr wymagań (xlsx — git go nie scali). Master dodał LOG-34, gałąź demo PRE-28 i PRE-29, żaden wspólny wiersz się nie różnił. Scalone ręcznie, sprawdzone: 148 pozycji, wszystkie trzy obecne.

Ponieważ #74 nigdy nie wszedł, astrodemo nie jest nigdzie wdrożone — zmiana nazw niczego nie migruje i nikogo nie wylogowuje.

Wycieki

astrodemo powstało przed audytem, więc miało komplet tych samych dziur co astrololo:

  • /static omijało bramkę, a pierwszy komentarz w styles.css brzmiał „Nie kopiujemy stylów pełnej aplikacji". Anonimowy curl dowiadywał się, że istnieje pełna aplikacja.
  • Komunikat awarii wypisywał treść wyjątku httpx — z nazwą usługi i portem.
  • /health oddawał nazwę warstwy.
  • Dziesięć komentarzy i docstringów tłumaczyło decyzje przez porównanie z „pełną aplikacją". To ważniejsze, niż wygląda: obraz tej usługi się komuś oddaje, więc kto go dostanie, przeczyta też komentarze. Przepisane tak, żeby opisywały tę usługę samą w sobie.
  • Nagłówek main.py twierdził, że demo dzieli pulę plików z produkcją — nieprawda od PRE-29.

Zapora słownikowa, dwupoziomowa

Poziom „wszędzie" (także w kodzie serwera, bo obraz się oddaje): wzmianki o większym rodzeństwie, o modelu językowym, o funkcjach, których tu nie ma. Poziom „do przeglądarki" dokłada słownictwo mechanizmów. Test sprawdza odpowiedzi oraz drzewo plików.

Jeden wyjątek jest jawny i opisany: stałe protokołu łącza (X-Astrololo-Token, X-Astrololo-Enc, typ treści, etykieta HKDF) niosą nazwę rodziny produktów. Są wspólne z warstwą logiczną, więc zmiana wymaga jednoczesnej podmiany we wszystkich usługach i rotacji sekretów — to osobna decyzja. Osobny test pilnuje warunku, pod jakim to zostaje: że nie docierają do przeglądarki.

Warto wiedzieć, że wcześniej przechodziły tylko dlatego, że mój regex nie dopasowywał po myślniku. To był przypadek, nie decyzja — sprawdziłem, czy ta ślepa plamka nie kryje czegoś jeszcze (nie kryje) i zamieniłem ją w jawny wyjątek.

Przy okazji

Komunikat "ramka bez znacznika astrololo" zmieniony na neutralny we wszystkich pięciu kopiach link_crypto.py. Tak — pięciu: presentation, astrodemo, logic, data, render, po 525 linii każda. To 2625 linii tego samego kodu i najlepszy argument za rdzeniem współdzielonym z PR 3.

Testy

astrodemo 27 · presentation 358 · logic 342 · data 42 · render 41.


Następne kroki: (2) wydzielenie AI w astrololo do app/ai/, (3) rdzeń współdzielony, (4) nowa usługa astroklient, (5) CI i compose. Przed PR 4 potrzebuję decyzji o zakresie astroklienta — Skompiluj, Ustawienia, eksport, geokoder.

Pierwszy z pięciu kroków budowy trzech produktów. **Zastępuje #74** — tamten PR stoi na nieaktualnym masterze i na starej nazwie, można go zamknąć. Nazwa `astroklient` zostaje zwolniona dla warstwy pośredniej, więc dotychczasowe `astroklient-demo` to teraz **astrodemo**. ### Rebase Cztery commity demo przeniesione na aktualnego mastera. Konflikt był jeden: rejestr wymagań (xlsx — git go nie scali). Master dodał LOG-34, gałąź demo PRE-28 i PRE-29, żaden wspólny wiersz się nie różnił. Scalone ręcznie, sprawdzone: 148 pozycji, wszystkie trzy obecne. Ponieważ #74 nigdy nie wszedł, **astrodemo nie jest nigdzie wdrożone** — zmiana nazw niczego nie migruje i nikogo nie wylogowuje. ### Wycieki astrodemo powstało przed audytem, więc miało komplet tych samych dziur co astrololo: - **`/static` omijało bramkę**, a pierwszy komentarz w `styles.css` brzmiał *„Nie kopiujemy stylów pełnej aplikacji"*. Anonimowy `curl` dowiadywał się, że istnieje pełna aplikacja. - **Komunikat awarii** wypisywał treść wyjątku `httpx` — z nazwą usługi i portem. - **`/health`** oddawał nazwę warstwy. - **Dziesięć komentarzy i docstringów** tłumaczyło decyzje przez porównanie z „pełną aplikacją". To ważniejsze, niż wygląda: obraz tej usługi się **komuś oddaje**, więc kto go dostanie, przeczyta też komentarze. Przepisane tak, żeby opisywały tę usługę samą w sobie. - **Nagłówek `main.py`** twierdził, że demo dzieli pulę plików z produkcją — nieprawda od PRE-29. ### Zapora słownikowa, dwupoziomowa Poziom **„wszędzie"** (także w kodzie serwera, bo obraz się oddaje): wzmianki o większym rodzeństwie, o modelu językowym, o funkcjach, których tu nie ma. Poziom **„do przeglądarki"** dokłada słownictwo mechanizmów. Test sprawdza odpowiedzi **oraz drzewo plików**. Jeden wyjątek jest jawny i opisany: stałe protokołu łącza (`X-Astrololo-Token`, `X-Astrololo-Enc`, typ treści, etykieta HKDF) niosą nazwę rodziny produktów. Są wspólne z warstwą logiczną, więc zmiana wymaga jednoczesnej podmiany we wszystkich usługach i rotacji sekretów — to osobna decyzja. Osobny test pilnuje warunku, pod jakim to zostaje: **że nie docierają do przeglądarki**. Warto wiedzieć, że wcześniej przechodziły tylko dlatego, że mój regex nie dopasowywał po myślniku. To był przypadek, nie decyzja — sprawdziłem, czy ta ślepa plamka nie kryje czegoś jeszcze (nie kryje) i zamieniłem ją w jawny wyjątek. ### Przy okazji Komunikat `"ramka bez znacznika astrololo"` zmieniony na neutralny we **wszystkich pięciu** kopiach `link_crypto.py`. Tak — pięciu: presentation, astrodemo, logic, data, render, po 525 linii każda. To 2625 linii tego samego kodu i najlepszy argument za rdzeniem współdzielonym z PR 3. ### Testy astrodemo 27 · presentation 358 · logic 342 · data 42 · render 41. --- **Następne kroki:** (2) wydzielenie AI w astrololo do `app/ai/`, (3) rdzeń współdzielony, (4) nowa usługa astroklient, (5) CI i compose. Przed PR 4 potrzebuję decyzji o zakresie astroklienta — Skompiluj, Ustawienia, eksport, geokoder.
gitea added 5 commits 2026-08-26 10:06:11 +00:00
Osobna warstwa prezentacji: dodanie pliku bazy i zapytanie o interpretację
urodzeniową. Nic więcej.

OSOBNA USŁUGA, NIE KONTO Z OGRANICZENIAMI. Mechanizm uprawnień z PRE-27 umiałby to
ukryć w pełnej aplikacji, ale ukrycie a nieobecność to dwie różne rzeczy: tutaj
pozostałych funkcji NIE MA W OBRAZIE — nie ma tras, nie ma szablonów, nie ma nawet
metod w kliencie warstwy logicznej. Demo można komuś oddać, nie oddając przy
okazji kodu reszty programu. Test porównuje zbiór tras aplikacji i zbiór metod
klienta z listą dokładną, więc dopisanie czegokolwiek zapala się od razu.

WGRANIE I WŁĄCZENIE TO JEDNA CZYNNOŚĆ. W pełnej aplikacji to dwie osobne decyzje
(DAN-27), bo tam ktoś nad tym panuje. Tutaj „dodać plik do bazy" musi znaczyć, że
plik od razu bierze udział w wyszukiwaniu — inaczej po wgraniu nic by się nie
zmieniło i demo wyglądałoby na zepsute. Walidacja zostaje: plik o złym układzie nie
wchodzi do użytku, ale też NIE JEST tracony, a komunikat nie zdradza reguł, bo te
zna wyłącznie administrator. Osobny test szuka w komunikacie śladów mechanizmu.

KONTO OSOBNE (DEMO_USER/DEMO_PASSWORD), nie współdzielone z główną aplikacją.
Demo pracuje na TEJ SAMEJ warstwie danych co produkcja — świadoma decyzja
właściciela — więc kto ma do niego dostęp, czyta oryginalne bazy, a jego wgrania
trafiają do produkcyjnego zbioru. Własne poświadczenia pozwalają odciąć demo jedną
zmienną, bez ruszania kont głównej aplikacji i bez zmiany hasła komukolwiek.
Zapisane wprost w README usługi i w manifeście, nie tylko w tej wiadomości.

Rozmowa z warstwą logiczną idzie tym samym szyfrowanym łączem (PRE-16) i pod tym
samym tokenem międzywarstwowym (LOG-32) — demo nie jest furtką omijającą ochronę.
Automatyczna dokumentacja wyłączona, jak w pełnej aplikacji: /docs wypisałoby
komplet tras, a demo ma nie zdradzać nawet własnej powierzchni.

Zależności celowo krótsze niż w prezentacji: bez Excela, bez stref czasowych
z lokalizacji, bez niczego pod kosmogram. Każda zbędna zależność w obrazie demo to
kolejna rzecz do pilnowania.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Demo ma być rozdawane szeroko i różnym osobom, więc pierwsza wersja — jedno konto
na produkcyjnej warstwie danych — nie nadawała się do użycia: każdy dostawałby
dostęp do oryginalnych baz, a wgrania jednego klienta widzieliby wszyscy.

IZOLACJA OD PRODUKCJI. Warstwa danych i logiczna demo są osobne (manifesty w repo
deploy). Osobna musi być TEŻ LOGICZNA, bo zna ona jeden adres warstwy danych —
demo korzystające z produkcyjnej logiki i tak trafiłoby na produkcyjne bazy.

PULE PER KONTO w warstwie danych. Zapytanie i lista plików niosą nazwę puli;
puste = cały udział, czyli produkcja działa dokładnie jak dotąd i o pulach nic
nie wie. Nazwa puli przechodzi przez sito dopuszczające wyłącznie znaki bezpieczne
w nazwie katalogu — „../..” albo ukośnik wyprowadziłyby zapytanie wprost do cudzych
baz, więc sito ZAMIENIA podejrzane znaki zamiast ufać, że nikt ich nie poda.

PULA MUSI BYĆ W KLUCZU CACHE ZAPYTAŃ. Bez tego wynik policzony dla jednego konta
trafiłby z cache do drugiego — cicha wymiana treści baz między klientami,
niewidoczna w logach i nie do wykrycia z zewnątrz. Osobny test tego pilnuje.

PULA WYNIKA Z LOGINU, nigdy z żądania. Klient warstwy logicznej jest budowany
per żądanie i związany z pulą zalogowanej osoby; gdyby nazwa przychodziła
z formularza, wystarczyłoby podstawić cudzy login. Test wysyła `tenant`, `user`
i `login` w polach formularza i sprawdza, że nie mają na nią wpływu.

Pulę wstrzykujemy w INSTANCJĘ klienta, nie w sygnatury metod. Argumentem trzeba
by ją przeprowadzić przez protokół DataSource i build_report — kod, który o kontach
nie ma prawa nic wiedzieć — a każde nowe wywołanie byłoby okazją, żeby o nią
zapomnieć i sięgnąć nie tam.

Konta demo to lista `login:sekret` (DEMO_USERS), bo jedno wspólne konto oznaczałoby
wspólną pulę. Format i skrypt haseł te same, co w głównej aplikacji.

Pula klienta to JEDEN KATALOG, więc przejście na pełną wersję nie oznacza utraty
wgrań — procedurę importu opisuje runbook w repo deploy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nazwa `astroklient` zostaje zarezerwowana dla przyszłej wersji produkcyjnej
programu; obecna, demonstracyjna nazywa się od teraz `astroklient-demo`.

Zmiana obejmuje katalog usługi, nazwę pliku testów, obraz w rejestrze
(astrololo-astroklient-demo), job w CI, pętlę budowania obrazów, tytuł i nagłówek
strony, nazwy loggerów, realm logowania, pole `layer` w /health oraz wymagania
PRE-28/29 w xlsx.

DWIE PUŁAPKI PODMIANY, obie sprawdzone po fakcie:

Zdublowany przyrostek. `astroklient-demo` zawiera `astroklient`, więc powtórna
podmiana dałaby `astroklient-demo-demo`. Sprawdziłem najpierw, że nigdzie nie ma
jeszcze nowej nazwy, i dopiero wtedy podmieniłem raz.

Polska odmiana. Ślepa podmiana zamieniła „astroklienta" na „astroklient-demoa”
w czterech miejscach; poprawione na „astroklienta-demo". Tytuł FastAPI wyszedłby
jako „astroklient-demo · demo", a nazwa jobu jako „Testy astroklienta-demo
(wersja demo)" — oba skrócone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Demo idzie szeroko i do różnych osób, często na cudzych komputerach — więc
wyjście z aplikacji jest tu potrzebne bardziej niż w pełnej wersji, a Basic go
nie miał: przeglądarka zapamiętuje hasło i dosyła je sama przy każdym żądaniu.
Pierwszy klient zostawiał otwartą sesję drugiemu.

Ta sama konstrukcja co w pełnej aplikacji: własny ekran logowania, podpisane
ciasteczko (HMAC-SHA256), HttpOnly + SameSite=Strict, wylogowanie POST-em, kres
bezczynności i twardy, sito na adres powrotu, zdarzenia w dzienniku bez haseł.
Moduł session.py skopiowany, tak samo jak link_crypto — usługi są osobnymi
obrazami i nie importują się nawzajem.

DWIE RÓŻNICE WOBEC PEŁNEJ WERSJI, obie wynikające z tego, że demo nie ma
własnego wolumenu:

  * nazwa ciasteczka jest inna. Gdyby obie aplikacje stanęły kiedyś pod jedną
    domeną, ciasteczka o tej samej nazwie nadpisywałyby się i człowiek wypadałby
    z jednej, logując się do drugiej.
  * nie ma licznika pokolenia sesji, bo nie ma go gdzie zapisać. Zdalne
    unieważnienie robi się przez DEMO_USERS: usunięcie konta albo zmiana hasła
    NATYCHMIAST ubija jego otwarte sesje, bo odcisk poświadczenia w ciasteczku
    przestaje pasować. Osobny test tego pilnuje. Wylogowanie i tak działa
    natychmiast, bo polega na skasowaniu ciasteczka.

Klucz podpisu jest 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.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
astrodemo: zmiana nazwy, rebase na mastera i domknięcie wycieków
Testy / Testy warstwy logicznej (silnik) (push) Failing after 4m50s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m28s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m25s
Testy / Testy astrodemo (push) Successful in 9m25s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 8s
Testy / Kontrola składni wszystkich warstw (push) Successful in 5s
Testy / Testy warstwy logicznej (silnik) (pull_request) Failing after 4m43s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m28s
Testy / Testy warstwy bazodanowej (ochrona baz) (pull_request) Successful in 9m25s
Testy / Testy astrodemo (pull_request) Successful in 9m25s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 6s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 4s
2e9d3706ec
Pierwszy z pięciu kroków budowy trzech produktów: astrodemo (dwie funkcje) →
astroklient (pełne astro bez AI) → astrololo (wszystko). Nazwa „astroklient"
zostaje zwolniona dla warstwy pośredniej, więc dotychczasowe astroklient-demo
nazywa się teraz astrodemo.

REBASE. Cztery commity demo przeniesione na aktualnego mastera. Konflikt był
jeden — rejestr wymagań (xlsx, binarny, git go nie scali). Master dodał LOG-34,
gałąź demo PRE-28 i PRE-29; żaden wspólny wiersz się nie różnił, więc scalone
ręcznie: 148 pozycji, wszystkie trzy obecne.

ZMIANA NAZWY. Katalog, ciasteczko sesji (astrodemo_sesja), zmienne
ASTRODEMO_USERS/USER/PASSWORD, CI, README, docstringi. Ponieważ PR z demo nigdy
nie został zmergowany, usługa nie jest nigdzie wdrożona — zmiana nazw niczego
nie migruje i nikogo nie wylogowuje.

WYCIEKI. astrodemo powstało przed audytem z PRE-27, więc miało komplet tych
samych dziur:

- /static omijało bramkę (PUBLIC_PREFIXES), a pierwszy komentarz w styles.css
  brzmiał „Nie kopiujemy stylów pełnej aplikacji" — czyli anonimowy curl
  dowiadywał się, że istnieje pełna aplikacja. Zasoby idą teraz trasą z jawną
  listą, komentarze są zdejmowane przy serwowaniu.
- Komunikat awarii wypisywał na ekran treść wyjątku httpx, z nazwą usługi
  i portem. Teraz jedno neutralne zdanie, szczegóły do dziennika.
- /health oddawał nazwę warstwy. Teraz samo „ok".
- Dziesięć komentarzy i docstringów tłumaczyło decyzje przez porównanie
  z „pełną aplikacją". Obraz tej usługi się KOMUŚ ODDAJE, więc kto go dostanie,
  przeczyta też komentarze. Przepisane tak, żeby opisywały tę usługę samą
  w sobie.
- Nagłówek main.py twierdził, że demo dzieli pulę plików z produkcją. To
  nieprawda od PRE-29 (pule per konto) — opis poprawiony.

ZAPORA SŁOWNIKOWA, dwupoziomowa. Poziom „wszędzie" (także w kodzie serwera, bo
obraz się oddaje) obejmuje wzmianki o większym rodzeństwie, o modelu językowym
i o funkcjach, których tu nie ma. Poziom „do przeglądarki" dokłada słownictwo
mechanizmów. Test sprawdza odpowiedzi ORAZ drzewo plików.

Jeden wyjątek jest jawny i opisany: stałe protokołu łącza (X-Astrololo-Token,
X-Astrololo-Enc, typ treści, etykieta HKDF) niosą nazwę rodziny produktów. Są
wspólne z warstwą logiczną, więc zmiana wymaga jednoczesnej podmiany we
wszystkich usługach i rotacji — osobna decyzja. Osobny test pilnuje warunku, pod
jakim to zostaje: że nie docierają do przeglądarki. Wcześniej przechodziły tylko
dlatego, że regex nie dopasowywał po myślniku — przypadek, nie decyzja.

Przy okazji: komunikat „ramka bez znacznika astrololo" zmieniony na neutralny we
WSZYSTKICH PIĘCIU kopiach link_crypto.py (presentation, astrodemo, logic, data,
render), żeby nie rozjechały się przed scaleniem w rdzeń. Te kopie to 2625 linii
tego samego kodu.

Testy: astrodemo 27, presentation 358, logic 342, data 42, render 41.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gitea added 1 commit 2026-08-26 13:50:55 +00:00
astrodemo: do obrazu wchodzi wyłącznie kod aplikacji
Testy / Testy warstwy logicznej (silnik) (pull_request) Failing after 4s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Failing after 4s
Testy / Testy warstwy bazodanowej (ochrona baz) (pull_request) Failing after 4s
Testy / Testy astrodemo (pull_request) Failing after 3s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 5s
Testy / Kontrola składni wszystkich warstw (pull_request) Failing after 3s
build-render / build (push) Failing after 8s
build / build (push) Successful in 20s
Testy / Testy warstwy logicznej (silnik) (push) Failing after 4s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Failing after 3s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Failing after 3s
Testy / Testy astrodemo (push) Failing after 3s
Testy / Build obrazu silnika B (swisseph) (push) Failing after 2s
Testy / Kontrola składni wszystkich warstw (push) Failing after 3s
10ade55525
`COPY . .` wnosiło do obrazu cały katalog usługi, razem z tests/. Leży tam plik
pilnujący, żeby pewne słowa nie padły — wypisujący je wprost, bo inaczej nie da
się ich sprawdzić. Trafiając do obrazu, stawał się dokładnie tym wyciekiem,
przed którym broni: „pełna aplikacja", „astrololo", nazwy nieobecnych funkcji.

Obraz tej usługi się KOMUŚ ODDAJE, więc waży to więcej niż gdzie indziej.
To samo zawężenie zrobiłem wcześniej w warstwie prezentacji; astrodemo zostało
przeoczone, bo powstało przed tamtą zmianą.

Test pilnuje tego na przyszłość i czyta same instrukcje, bez komentarzy —
komentarz obok cytuje dawną postać, więc szukanie po całym pliku zgłaszałoby
własne wyjaśnienie.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gitea merged commit 10ade55525 into master 2026-08-26 14:25:29 +00:00
gitea deleted branch feat/astrodemo 2026-08-26 14:25:29 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: gitea/astrololo#79