gitea 71bb3b9c0a
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m17s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m29s
Testy / Testy warstwy bazodanowej (ochrona baz) (pull_request) Successful in 9m25s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 5s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 4s
build / build (push) Successful in 1m18s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m21s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m29s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m25s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 5s
Testy / Kontrola składni wszystkich warstw (push) Successful in 4s
feat(bezpieczeństwo): przycisk wylogowania (LOG-32)
Aplikacja nie miała jak z siebie wyjść: raz podane hasło działało do zamknięcia
przeglądarki, a na wspólnym komputerze nie było sposobu, żeby oddać ekran komuś
innemu.

HTTP BASIC NIE MA PRAWDZIWEGO WYLOGOWANIA i to jest sedno tej zmiany. Nie ma
sesji do skasowania: przeglądarka zapamiętuje login i hasło, po czym dosyła je
SAMA przy każdym żądaniu. Serwer nie ma czego zapomnieć — kolejne kliknięcie
przyszłoby z kompletem poświadczeń i weszłoby z powrotem.

Działa natomiast doprowadzenie do tego, żeby to PRZEGLĄDARKA porzuciła zapamiętane
dane, i robimy to dwutorowo, bo ani jedno, ani drugie osobno nie wystarcza:

  1. /wyloguj odpowiada ZAWSZE 401 z nagłówkiem WWW-Authenticate, co wymusza
     ponowne pytanie o hasło. Działa bez JavaScriptu, ale samo w sobie zostawia
     stare dane w pamięci przeglądarki: po anulowaniu okienka wystarczyłoby wejść
     na dowolny adres, żeby wrócić do środka.
  2. wyloguj.js wysyła żądanie z CELOWO błędnymi danymi, którym przeglądarka
     nadpisuje swój wpis. To jest część, która faktycznie czyści pamięć — ale
     opiera się na zachowaniu powszechnym, a nie zapisanym w standardzie, więc
     nie może być jedynym mechanizmem.

Strona wylogowania mówi wprost, że pewnym sposobem w KAŻDEJ przeglądarce jest
zamknięcie okna. Nie obiecujemy więcej, niż Basic potrafi — obietnica bez pokrycia
byłaby tu gorsza od braku przycisku, bo dawałaby złudzenie, że ekran jest oddany.

Trasa stoi POZA bramką logowania, celowo: inaczej dostałaby 200 od zalogowanej
sesji i nie miałaby jak odpowiedzieć 401. Odpowiada też bez logowania — inaczej
wyjście wymagałoby bycia w środku, co jest błędnym kołem. Nagłówki zakazują
zapamiętania strony, bo oddana z pamięci podręcznej nie dotarłaby do serwera
i okienko w ogóle by się nie pojawiło.

Obok wyjścia pokazujemy, KTO jest zalogowany: bez tego przycisk jest w połowie
bezużyteczny, bo na wspólnym komputerze nie wiadomo, kogo się wylogowuje. Przy
wyłączonym logowaniu nie ma ani jednego, ani drugiego — przycisk sugerowałby
ochronę, której nie ma.

Sprawdzone w przeglądarce: oba żądania wychodzą (to z błędnymi danymi i samo
przejście), oba wracają 401, strona renderuje się poprawnie. Samego unieważnienia
pamięci poświadczeń NIE dało się tu potwierdzić — wymaga okienka systemowego,
którego automat nie obsłuży.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 23:52:04 +02:00
2026-07-28 22:28:47 +02:00
2026-07-20 19:52:21 +02:00

astrololo

Aplikacja w modelu trójwarstwowym, w pełni modułowa: trzy niezależne usługi, każda komunikuje się wyłącznie z sąsiadem (nigdy „przez głowę”).

┌──────────────────────┐   formularz (w dół)   ┌──────────────────────┐   zapytanie (w dół)   ┌──────────────────────┐
│  PREZENTACJA (:8000) │ ───────────────────▶ │   LOGICZNA (:8001)   │ ───────────────────▶ │  BAZODANOWA (:8002)  │
│  strona WWW + form   │ ◀─────────────────── │  reguły biznesowe    │ ◀─────────────────── │  wyszukiwanie danych │
└──────────────────────┘   wyniki (w górę)     └──────────────────────┘   dane (w górę)       └──────────────────────┘
        HTML/UI                                    pośrednik + logika                         Excel(+cache) ▸ SQL

Każda warstwa to osobny katalog, osobny requirements.txt, osobny Dockerfile i osobne README. Komunikacja przez HTTP/JSON. Warstwa zna tylko adres warstwy bezpośrednio pod nią — nic o jej wnętrzu.

Warstwa Katalog Zna w dół Zadanie
Prezentacji services/presentation LOGIC_URL serwuje stronę, przekazuje formularz, renderuje wyniki
Logiczna services/logic DATA_URL reguły biznesowe, tłumaczenie zapytań, opracowanie wyników
Bazodanowa services/data pliki Excela / SQL tylko wyszukiwanie danych i podanie ich w górę

Szybki start (Docker)

make sample      # przykładowe pliki .xlsx do warstwy bazodanowej
make up          # zbuduj i uruchom 3 warstwy
# otwórz http://localhost:8000

Szybki start (lokalnie, bez Dockera — zalecane)

python -m venv .env && source .env/bin/activate   # venv (jednorazowo)
make install                                       # zależności WSZYSTKICH warstw
make sample                                        # opcjonalnie: dane przykładowe

Potem w 3 osobnych terminalach (w każdym source .env/bin/activate):

make dev-data            # terminal 1  -> :8002
make dev-logic           # terminal 2  -> :8001
make dev-presentation    # terminal 3  -> :8000   ->  http://localhost:8000

make install instaluje zależności wszystkich trzech warstw do aktywnego venv. Testy silnika: make test. Wyczyszczenie cache: make clean-cache.

Modułowość — dowód

  • Wymień prezentację (np. na SPA/React) → reszta bez zmian, kontrakt /api/query stały.
  • Wymień bazę (Excel → SQL) → prezentacja i logika bez zmian (patrz niżej).
  • Każdą warstwę da się uruchomić, testować i wdrażać osobno.

Wydajność warstwy Excela — cache 4-poziomowy

Dziś dane to setki dużych .xlsx, przeszukiwanych po wykrytym nagłówku i układzie kolumn. To kosztowne, więc warstwa bazodanowa ma cache (szczegóły: services/data/README.md):

  1. Schemat (L1, SQLite) — wykryty nagłówek + mapowanie kolumn zapisane raz na wersję pliku.
  2. Dane (L2, Parquet) — znormalizowany arkusz; kolejne odczyty 10100× szybsze niż .xlsx.
  3. Zapytania (L3, in-memory TTL/LRU) — powtarzalne wyszukiwania natychmiast (łatwo podmienić na Redis).
  4. Odwrócony indeks (L4, SQLite)wartość → plik; otwieramy tylko trafione pliki zamiast skanu setek.

Unieważnianie automatyczne: klucz cache = odcisk pliku (mtime+rozmiar, opcjonalnie sha256). Zmiana pliku → przebudowa tylko jego wpisów.

Droga na przyszłość — migracja do SQL

Warstwa bazodanowa ukrywa źródło za interfejsem DataProvider (wzorzec Repository). Migracja:

make migrate                 # ETL: tym samym loaderem Excel -> tabela 'records' + indeksy
export DATA_PROVIDER=sql      # przełącz całą warstwę

SqlDataProvider realizuje ten sam kontrakt /search, więc warstwa logiczna i prezentacji nie zmieniają ani jednej linii. Odwrócony indeks z L4 (SQLite) jest już pomostem — rozbudowa o wszystkie kolumny = docelowa baza.

updater test Mon 20 Jul 2026 19:52:08 CEST

S
Description
No description provided
Readme 3.8 MiB
Languages
Python 86.4%
HTML 6.2%
JavaScript 3.8%
CSS 2.9%
Dockerfile 0.4%
Other 0.3%