Koch Laboratory

Laborbuch — podręcznik administratora

Profil laboratorium, projekty, użytkownicy i 2FA, storno, tłumaczenia, zamknięcia tygodni, kopie, licencja, aktualizacje.

Podręcznik administratora instancji Laborbuch — konfiguracja, użytkownicy, zamykanie tygodni, kopie i licencja. Codzienną pracę opisuje podręcznik użytkownika.

Panel admina

Panel jest pod adresem /admin/ (logowanie tym samym kontem i 2FA co do dziennika — panelu nie da się otworzyć z pominięciem 2FA). Dostęp mają konta z uprawnieniem „w zespole” (staff); pełną konfigurację robi superużytkownik utworzony przy instalacji.

Pierwsza konfiguracja — Ustawienia strony

Ustawienia strony → Profil laboratorium dopasowuje system do charakteru pracy:

Ustawienie Znaczenie
Integracja Git/GitHub Repozytoria, synchronizacja commitów i kotwice commitowe — profil IT/hardware; wyłącz w laboratorium bez kodu
Kotwice plikowe (uploady) Załączanie plików dowodowych do wpisów
Tryb kotwic plikowych Upload — plik przechowywany w instancji; Hash-only — plik zostaje u użytkownika, system zapisuje tylko odcisk SHA-256 (tajemnica przedsiębiorstwa nigdy nie trafia na serwer)

Projekty

Projekty → Dodaj: nazwa, slug, Kod Vorhaben (odwzorowanie na wniosek BSFZ), opis odgraniczenia B+R od rutyny. Dwie listy osób:

Nowe konto trafia domyślnie do członków wszystkich aktywnych projektów, a nowy projekt dostaje wszystkie istniejące konta. Wykluczenie kogoś z projektu to świadome usunięcie z listy Członkowie — raz usunięta osoba nie zostanie dopisana ponownie.

Przy włączonym Git dodaj projektowi Repozytoria (format owner/nazwa; token dostępu ustawia się w konfiguracji instancji jako GITHUB_TOKEN). Commity pobierają się co 15 minut; ręcznie: przycisk w dashboardzie albo akcja Synchronizuj commity z GitHub w adminie.

Token typu fine-grained obejmuje repo tylko jednego właściciela zasobów, więc repo organizacji jest dla tokena konta osobistego niewidoczne (GitHub odpowiada wtedy 404, nie 403). Takie repo dostaje własny token w polu Token dostępowy — wystaw go na organizację (Resource owner = organizacja, wybrane repo, uprawnienie Contents: Read-only), a organizacja musi mieć włączony dostęp przez fine-grained PAT. Puste pole = token globalny. Akcja Sprawdź dostęp GitHub weryfikuje konfigurację bez pobierania commitów.

Użytkownicy i 2FA

Użytkownicy → Dodaj: login i hasło, potem w edycji konta uprawnienia („w zespole” dla dostępu do admina) i grupy ról (Badacz, Kierownik B+R, Redaktor CMS). Metodę 2FA deklarujesz per konto — na dole strony użytkownika:

Limit kont licencji liczy konta aktywne: przy wyczerpanym limicie nie dodasz ani nie aktywujesz konta — dezaktywacja (odznaczenie „aktywny”) zwalnia miejsce bez utraty historii wpisów.

Parametry rozliczeniowe (sekcja na stronie konta) zawierają osobowy sufit tygodniowy. Puste pole = sufit globalny instancji, domyślnie 40 h, czyli reguła Eigenleistung wg §3 Abs. 3 FZulG. Dla pracownika wpisz wymiar jego umowy: godziny pracownika są kwalifikowane w wysokości rzeczywistej, więc przy pół etatu sufit wynosi 20 h, a nadgodziny pracownika nie są „B+R ponad sufit”. Ustawiony sufit widać także na dashboardzie danej osoby — w pasku tygodnia i jako linia na wykresie.

Które Vorhaben zajmują sufit. Sufit tygodniowy zajmują tylko godziny Vorhaben wskazanych przez administratora: Vorhaben → status BSFZ (edytowalny wprost z listy, kolumna „Wpływa na sufit”). Przed złożeniem wniosku nadaj Vorhaben z wniosku status „Złożony”. Po Bescheidzie zmień status certyfikowanych na „Certyfikowany”, a odrzuconych na „Odrzucony”: ich godziny przestają zajmować sufit i w tym samym tygodniu zwalnia się miejsce dla pracy „B+R ponad sufit” przy Vorhaben certyfikowanych. Praca nad innymi projektami i Vorhaben „Niezgłoszonymi” sufitu nie zajmuje. Dopóki żaden Vorhaben nie ma statusu „Złożony” ani „Certyfikowany”, sufit obejmuje wszystkie projekty łącznie. Wpis bez podziału na Vorhaben (np. dodany z dashboardu) zajmuje sufit, jeśli pole „Vorhaben” zawiera kod Vorhaben wpływającego na sufit; wpis z podziałem — sumą alokacji na takie Vorhaben.

Wpisy, korekty (storno) i tłumaczenia

Wpisy w adminie: pełna lista z filtrami. Wpis w otwartym tygodniu można poprawić; wpis zamknięty (🔒) jest tylko do odczytu — na zawsze.

Zamknięcie tygodnia — rytm pracy

Tydzień zamykasz przyciskiem w dashboardzie — kafelek „Tygodnie niezamknięte” pokazuje najstarszy zaległy tydzień i przycisk „Zamknij 2026-W29”. Nie trzeba logować się na serwer.

Przycisk widzą konta z rolą Kierownik B+R (uprawnienie core.add_weekclose) oraz superuser. Badacz dodaje wpisy, ale nie zamyka tygodni — zamknięcie blokuje pracę wszystkich autorów.

Trzy bariery, których przycisk pilnuje:

Ta sama operacja z konsoli, gdyby była potrzebna (np. w skrypcie migracyjnym):

docker compose exec web python manage.py close_week 2026-W29

Zamknięcie: buduje kanoniczny zapis wszystkich wpisów tygodnia → liczy SHA-256 → znakuje czasem w BeatTime (podpis Ed25519) i OpenTimestamps (kotwica w Bitcoinie) → blokuje wpisy (🔒). Dowody znajdziesz w Zamknięcia tygodni (odcisk, status, dowody stempli). Stempel OTS dojrzewa po potwierdzeniu w Bitcoinie — komenda upgrade_ots aktualizuje dowody.

Wpisy dopisane po zamknięciu. Zamknięcie blokuje edycję wpisów, które w nim były — ale nie blokuje dopisania nowego wpisu z datą pracy w tym tygodniu (reżim „rekonstrukcja”). Taki wpis nie wchodzi pod pieczęć: nie ma go w kanonicznym zapisie ani pod stemplem i już tam nie trafi. Raport pokazuje to wprost — kolumna „objęty pieczęcią” w CSV oraz oznaczenie „poza pieczęcią tygodnia” i ostrzeżenie nad tabelą w HTML/PDF.

Zasada: zamykaj tydzień wtedy, gdy jest w pełni opisany — nie wcześniej, ale i nie w nieskończoność. Otwarty tydzień to wpisy bez stempla; zamknięty za wcześnie to wpisy poza pieczęcią. Jeśli piszesz wpisy z opóźnieniem kilku tygodni, po prostu zamykaj z takim samym opóźnieniem.

Gdy stempel nie powstanie (brak sieci, usługa chwilowo niedostępna): tydzień zostaje zamknięty, zahaszowany i zablokowany, ale ze statusem „zamknięty”, nie „ostemplowany” — raport audytora pokaże dokładnie ten stan, bo status wynika z faktycznych dowodów, nie z samej próby. Nic nie trzeba robić: autopilot ponawia stempel przy kolejnym przebiegu, aż się uda. BeatTime i OpenTimestamps są niezależnymi kotwicami czasu — jedna skuteczna wystarczy.

Autopilot — co dzieje się samo

W kontenerze chodzi pętla (domyślnie co 15 minut), która wykonuje wszystko, co zaległe. Nie wymaga crona na serwerze ani żadnej konfiguracji — jedzie z obrazem.

Co Kiedy
pobranie commitów z GitHuba co przebieg
brakujące stemple zamkniętych tygodni co przebieg, z odstępem ≥ 1 h między próbami
dojrzewanie dowodów: OTS → konfirmacja Bitcoin, podpis tygodnia BeatTime co przebieg
tłumaczenia wpisów (TRANSLATE_AUTO_LANGS) co przebieg, partiami po 50 wpisów

Czego autopilot nie robi: nie zamyka tygodni. Zamknięcie blokuje wpisy nieodwracalnie, a do świeżo zakończonego tygodnia ktoś może jeszcze dopisywać zaległą pracę — dlatego decyzję podejmuje człowiek przyciskiem.

Podgląd zaległości bez wykonywania czegokolwiek:

docker compose exec web python manage.py autopilot --dry-run

Raport do wniosku w Finanzamcie

Zakładka Wniosek do Finanzamtu (/reports/fa/) zestawia godziny do wniosku o Forschungszulage, który składa się w ELSTER po zamknięciu roku obrotowego — jeden na rok, dla wszystkich Vorhaben z zaświadczeniem BSFZ. Raport niczego nie zmienia w księdze.

Co ustawić w panelu przed złożeniem wniosku:

Gdzie Co
Vorhaben → status BSFZ „Certyfikowany” dla Vorhaben z zaświadczeniem — tylko one wchodzą do zestawienia
Vorhaben → Sygnatura zaświadczenia / decyzji numer z zaświadczenia BSFZ; raport podaje go przy każdym Vorhaben
Vorhaben → Początek Vorhaben (z wniosku) data rozpoczęcia podana we wniosku do BSFZ; od niej zależy Pauschale 20 %
Użytkownicy → konto → Parametry rozliczeniowe → Eigenleistung zaznacz dla właściciela jednoosobowej firmy albo wspólnika; dla pracownika zostaw puste

Co liczy raport. Godziny z podziału wpisów na Vorhaben certyfikowane, z osobowym sufitem tygodniowym stosowanym chronologicznie: godziny ponad sufit odpadają z końca tygodnia, a raport je wykazuje. Wpisy „poza B+R” i „B+R ponad sufit” oraz godziny Vorhaben bez zaświadczenia nie wchodzą do zestawienia — raport pokazuje je osobno, informacyjnie. Dla osób z Eigenleistung raport szacuje kwotę według stawek z ustawy: 40 €/h do 27.03.2024, 70 €/h od 28.03.2024, 100 €/h od 2026 r.; do tego Pauschale 20 % na koszty ogólne (§ 3 ust. 3b FZulG) dla Vorhaben rozpoczętych po 31.12.2025; stopa 25 %, a dla KMU od 28.03.2024 wyższa o 10 pkt proc. (przełącznik w filtrach). Dla pracownika raport podaje tylko godziny — podstawą jest jego wynagrodzenie z kadr. O kwocie rozstrzyga Bescheid Finanzamtu.

Kontrole przed złożeniem wniosku stoją na górze raportu: tygodnie niezamknięte (zamknij je przed złożeniem — pieczęć pokazuje, że zapisu nie zmieniano), godziny odcięte przez sufit, wpisy bez podziału na Vorhaben (nie wchodzą do zestawienia — uzupełnij podział we wpisie), dni ponad 20 h, Vorhaben bez daty rozpoczęcia albo sygnatury. Gdy wszystko jest w porządku, raport pokazuje „Wszystkie kontrole bez uwag”.

Eksport: filtr roku obrotowego albo dat Od/Do, PDF i CSV (separator ;, przecinek dziesiętny), wersje PL/DE/EN. Każde otwarcie raportu trafia do rejestru Odczyty (audyt).

We wniosku w ELSTER podajesz dla każdego Vorhaben numer zaświadczenia i godziny z tabeli. Podwyższona stopa dla KMU wymaga wniosku i oświadczenia o statusie KMU według definicji UE (z przedsiębiorstwami powiązanymi), a wniosek zawiera też oświadczenie o innych dotacjach na te same koszty. Raport, raport audytora i kotwice dowodowe wpisów (commity, pliki) przechowuj jako dowody — Finanzamt może o nie poprosić.

Kopie zapasowe

Pulpit admina → Kopie zapasowe bazy: utworzenie kopii (bez zatrzymywania systemu), lista z datami, Pobierz (odłóż kopię poza serwer!), Przywróć (automatycznie odkłada stan sprzed przywrócenia jako pre-restore-…) i Usuń. Kopia obejmuje bazę; pliki dowodowe w media/ wymagają osobnej kopii katalogu. Operacje trafiają do dziennika audytu.

Audyt odczytów

Odczyty (audyt) — append-only rejestr: kto i kiedy otwierał raporty, pobierał pliki dowodowe, tworzył i przywracał kopie. Wpisów nie da się zmienić ani usunąć — przy tajemnicy przedsiębiorstwa odczyt bywa równie wrażliwy jak edycja.

Licencja

Plik license.json leży w katalogu instalacji. Stan widać na dashboardzie (klient, pakiet, limit kont, ważność). Po wygaśnięciu instancja przechodzi w tryb tylko-do-odczytu z pełnym eksportem — dane nigdy nie są zakładnikiem. Odnowienie: podmiana pliku na nowy (bez restartu). Rozszerzenie pakietu: nowy plik od dostawcy.

Aktualizacje

cd laborbuch && docker compose pull && docker compose up -d

Migracje bazy wykonują się automatycznie przy starcie. Obrazy są podpisane (cosign) — weryfikacja opisana na stronie produktu. Przed większymi aktualizacjami utwórz kopię zapasową.