Commit Graph

3 Commits

Author SHA1 Message Date
gitea 6466ab89a9 feat(dane): interfejs zarządzania plikami baz — trzy poziomy dostępu (DAN-27)
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m12s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m33s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 19s
Testy / Kontrola składni wszystkich warstw (push) Successful in 8s
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 12m25s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m33s
Testy / Testy warstwy bazodanowej (ochrona baz) (pull_request) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 16s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 8s
Ekran „Pliki" z trzema poziomami, wpiętymi w kontrolę dostępu z PRE-27:

  „files"        widzi listę i KLIKANIEM decyduje, z których baz program korzysta,
  „files_input"  dokłada wgrywanie i ARCHIWIZACJĘ,
  administrator  kasowanie, przywracanie z archiwum i REGUŁY WALIDACJI.

STAN JEST TERAZ TRWAŁY. DAN-15 trzymał go w zmiennej DISABLED_BASES, bo warstwa
danych nie miała gdzie zapisywać — udział był montowany read-only. Skoro stan ma
być klikany, musi przetrwać restart, więc udział jest zapisywalny, a stan leży
w pliku obok baz (zapis atomowy: plik opisuje CAŁY zbiór, więc obcięcie w połowie
skasowałoby wiedzę o wszystkich naraz). DISABLED_BASES zostaje jako awaryjne
wyłączenie z konfiguracji i odsiewa DODATKOWO — nie odwrotnie, bo inaczej ktoś
z dostępem do ekranu włączyłby bazę wyłączoną świadomie na poziomie wdrożenia.

ARCHIWIZACJA NIE KASUJE. Plik zostaje na dysku, zamrożony, ze znacznikiem czasu;
znika wyłącznie z użytku. To najdalej idąca operacja osoby wgrywającej dane —
kasować może tylko administrator. Test sprawdza, że plik po archiwizacji nadal
istnieje, bo to jest cała istota tej operacji.

WALIDACJA JEST BRAMKĄ DO UŻYTKU, NIE FILTREM NA WEJŚCIU. Plik wgrany zostaje
NIEZALEŻNIE od wyniku — nie tracimy niczego, co ktoś wgrał. Zmienia się tylko to,
czy da się go włączyć. Sprawdzenie biegnie też w chwili włączania, nie tylko przy
wgrywaniu: reguły mogą się zmienić po fakcie.

O WALIDACJI WIE TYLKO ADMINISTRATOR. Pliki wstrzymane są odsiewane W WARSTWIE
DANYCH przy for_admin=False, a nie ukrywane w szablonie — gdyby dochodziły do
przeglądarki, wystarczyłby podgląd źródła, żeby poznać reguły. Odmowa włączenia
wraca do konta bez uprawnień BEZ POWODU, bo powód zdradza regułę. Sekcja reguł
nie trafia nawet do źródła strony. Test parametryzowany po obu niższych poziomach
szuka w odpowiedzi śladów mechanizmu i wymaga, żeby żadnego nie było.

Każdy plik ma policzony sha256 — tożsamość niezależna od nazwy. Wykorzystuje ją
już odrzucanie duplikatów, a w kroku drugim posłuży do pilnowania zgodności
lustra w SQL.

Przy okazji naprawiony błąd, który dopiero co bym wprowadził: Path("") to
Path("."), czyli wartość PRAWDZIWA, więc `Path(os.getenv(...)) or domyślna`
zawsze wybierało pustą zmienną i zapisywało stan do katalogu bieżącego.

Wymaga zapisywalnego udziału — osobny PR w repo deploy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 14:39:42 +02:00
gitea 4c1e7f8808 feat: przegląd baz na udziale + globalne włączanie/wyłączanie (DAN-15/PRE-09)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m30s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m29s
Testy / Testy warstwy bazodanowej (ochrona baz) (pull_request) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 12s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 8s
build / build (push) Successful in 40s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m3s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m35s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m29s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 14s
Testy / Kontrola składni wszystkich warstw (push) Successful in 10s
Wymaganie przedefiniowane pod model serwerowy (#47): nie wybiera się folderu —
pliki leżą na stałym NFS. Potrzeba za to WIDZIEĆ, jakie bazy są dostępne i móc
zdecydować, które biorą udział w interpretacji.

Warstwa danych: `bases.py` (lista plików + metaopis: nazwa, ścieżka, rozmiar,
data, stan) i endpoint `/bases`. Wyłączone bazy są ODSIEWANE z kandydatów przy
wyszukiwaniu, więc naprawdę nie biorą udziału w interpretacji — nie tylko znikają
z listy. Lista wyłączonych wchodzi do klucza cache zapytań: bez tego zmiana
ustawień oddawałaby wynik sprzed zmiany, czyli treść bazy uznanej za wyłączoną.
`list_bases()` doszło do interfejsu dostawcy jako OPCJONALNE (SQL nie operuje na
plikach → pusto, zamiast wywrotki).

Przelot logika → prezentacja i ekran „Ustawienia" z tabelą baz. Przez łącze idą
SAME METADANE — podgląd listy nie jest kolejną drogą do wyniesienia treści.

Stan przełączników jest DEKLARATYWNY (`DISABLED_BASES`), nie klikalny — i to jest
świadome: udział z bazami montujemy read-only, a katalog cache to `emptyDir`, więc
zapisany przełącznik ginąłby przy restarcie poda i po cichu włączał z powrotem
wyłączoną bazę. Ekran mówi wprost, jak wyłączyć bazę i dlaczego nie klikaniem.
Tryb klikalny wymagałby dołożenia trwałego wolumenu.

Weryfikacja na żywym łańcuchu: `/bases` przechodzi przez SZYFROWANE łącze
(logic→data), pokazuje 3 bazy z metaopisem i stanem; wyszukiwanie daje 3 → 2 → 0
wierszy w miarę wyłączania baz. Testy: dane +6, prezentacja +6. Dane 13,
logika 277, prezentacja 249.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 22:09:27 +02:00
gitea 78af6d4755 feat(dane): mechanizm rekordów-pułapek (canary) — wykrywanie wycieku baz (DAN-26)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m29s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 11s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 8s
build / build (push) Successful in 19s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m30s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 11s
Testy / Kontrola składni wszystkich warstw (push) Successful in 7s
Zabezpieczenie DETEKCYJNE (nie prewencyjne): kilka unikalnych, wiarygodnie
wyglądających rekordów-pułapek w bazach. Nie zmieniają interpretacji (odsiewamy
je z wyników), ale jeśli pojawią się w cudzej kopii — są dowodem pochodzenia, a
przy wariancie na kopię — wskazują ŹRÓDŁO wycieku.

`canary.py`: pułapkę rozpoznajemy po MARKERZE (unikalny ciąg z ENV, nieobecny w
realnych danych). `screen(rows, query_value)`:
- ODSIEWA rekordy z markerem z wyników — i to na WYJŚCIU z warstwy danych
  (`/search`), więc nie dotrą wyżej ani do promptu LLM (LOG-30), niezależnie od
  dostawcy (Excel/SQL);
- TRIPWIRE: gdy zapytanie celuje wprost w marker (enumeracja bazy, nie liczenie
  horoskopu) → log warning.
Bez `CANARY_MARKERS` — przezroczyste, zero kosztu dla normalnego ruchu.

Rejestr wariant→kopia (traitor tracing) i wstrzyknięcie do REALNYCH baz to krok
właściciela (poza kodem — nie ruszamy kupionych plików automatycznie);
instrukcja: docs/canary-registry.md. Mechanizm zbudowany i przetestowany na
syntetycznych pułapkach.

Testy: +7 (przezroczystość bez markerów, odsiewanie, tripwire, marker w dowolnym
polu, endpoint odsiewa przed zwrotem). Pierwsze testy w usłudze `data`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 21:15:53 +02:00