Skip to content

feat(kompletnosc_polon): raport kompletności danych wg rozporządzenia POL-on 2026 (FD#437)#682

Open
mpasternak wants to merge 6 commits into
devfrom
feat-fd437-kompletnosc-polon
Open

feat(kompletnosc_polon): raport kompletności danych wg rozporządzenia POL-on 2026 (FD#437)#682
mpasternak wants to merge 6 commits into
devfrom
feat-fd437-kompletnosc-polon

Conversation

@mpasternak

Copy link
Copy Markdown
Member

Co i po co

Raport kompletności danych wymaganych rozporządzeniem MNiSW z 16 czerwca 2026 r. w sprawie danych przetwarzanych w POL-on (Dz. U. 2026 poz. 811, w życie od 30 czerwca 2026 r.). Zgłoszenie FD#437 — prorektor UAFM przysłał rozporządzenie z prośbą o dostosowanie systemu.

Rozpoznanie dało wynik odwrotny do oczekiwanego: BPP nie potrzebuje nowych pól. § 2 ust. 10 rozporządzenia wylicza praktycznie ten sam zestaw danych, który BPP już utrzymuje na potrzeby eksportu do PBN — łącznie z opłatami APC, pełnym blokiem Open Access i flagą artykułu recenzyjnego. Problemem nie jest brak miejsca na dane, tylko brak widoczności, których danych brakuje i przy kim.

Stąd raport, a nie migracja.

Jak to działa

Nowa aplikacja kompletnosc_polon, bez modeli i bez migracji. Trzy decyzje, które warto znać przy review:

Ziarno to para (autor, osiągnięcie), nie sama publikacja. Rozporządzenie umieszcza osiągnięcia w wykazie pracowników — dane wiszą przy człowieku, a każde osiągnięcie niesie własną dyscyplinę z art. 265 ust. 13. Ten sam artykuł u dwóch współautorów to w POL-onie dwa wpisy. Querysety startują więc z through-modeli (Wydawnictwo_Ciagle_Autor itd.).

Nie da się tego oprzeć na widoku Rekord. bpp_rekord_mat nie wystawia opłat APC ani flag ewaluacyjnych PBN, a strony/tom/nr_zeszytu ma jawnie wygaszone (RekordBase, src/bpp/models/cache/rekord.py:192-260). Jedna trzecia wymogów rozporządzenia byłaby przez ten widok niesprawdzalna.

Reguły są danymi, nie kodem. 50 reguł, każda to (kod, typ osiągnięcia, warunek Q, opis, paragraf, waga). Warunek jest obiektem Q, więc jedna definicja służy do liczenia, filtrowania i testu. Paragraf trafia do interfejsu — użytkownik widzi podstawę prawną, nie samo czerwone pole. Waga odróżnia wymogi bezwarunkowe od tych, które rozporządzenie opatruje słowami „jeżeli posiada" / „jeżeli są znane" — raport ich nie zaostrza.

Zakres

Objęte: artykuły (§ 2 ust. 10 pkt 4), monografie (pkt 5), rozdziały (pkt 6), patenty (pkt 1) — te ostatnie częściowo.

Poza zakresem, bo BPP nie ma gdzie tych danych trzymać:

Wymóg Paragraf
Osiągnięcia artystyczne pkt 7 — brak modelu w ogóle
Wzory użytkowe, odmiany roślin pkt 2, 3 — j.w.
Patenty: uprawniony, urząd udzielający, państwa ochrony, data ogłoszenia w WUP, uprzednie pierwszeństwo, streszczenie opisu, tłumaczenie patentu EP pkt 1 lit. b, d, e, f, h, i, j
ISMN pkt 5 lit. b
Czy monografia jest przekładem dzieła istotnego pkt 5 lit. i
Zgłoszenie do oceny eksperckiej KEN i jej wynik pkt 5 lit. l

Braki patentowe pokrywają się z tym, co niezależnie zgłosiła klientka w FD#449.

Recenzja adwersarialna — co znalazła

Kod przeszedł osobną recenzję przed wystawieniem PR. Znaleziska naprawione w 365fbd5c4, wszystkie zweryfikowane mutacyjnie (cofnięcie poprawki → odpowiadające testy padają):

  • Streszczenia zjazdowe audytowane jak artykuły naukowe. Wydawnictwo_Ciagle obejmuje w BPP także PSZ/ZSZ, listy do redakcji, recenzje i komunikaty. Raport żądał od streszczenia konferencyjnego numeru DOI. Uderzyłoby w każdą instalację z bibliografią zjazdową.
  • Monografia macierzysta rozdziału nie była sprawdzana nigdy. Komentarz w kodzie twierdził, że jej braki widać przy monografii — ale rodzic trafia do raportu tylko wtedy, gdy sam ma autora z uczelni, a rozdział w monografii zbiorowej pod obcą redakcją takiego rodzica nie ma. Cały pkt 6 lit. a wypadał z audytu.
  • Wyciek nazwisk między uczelniami. Widok szczegółów nie zawężał autora do uczelni; slug jest przewidywalny (nazwisko-imie), więc pozwalało to enumerować kadrę obcej instytucji. Teraz 404.
  • Trzy luki wobec rozporządzenia: brak reguły na sam tryb dostępu OA, dziura między regułami APC, całkiem pominięta lit. g o konferencjach.
  • Luka w testach: wzorzec zerował wszystkie człony koniunkcji naraz, więc dowolny fallback dało się usunąć z kodu przy zielonej suicie.

Recenzja potwierdziła też, że nie ma N+1 (45 zapytań przy 2 i przy 20 autorach), nie ma mnożenia wierszy przez JOIN-y i że wszystkie paragrafy przy regułach wskazują właściwą jednostkę redakcyjną rozporządzenia.

Testy

341 testów w src/kompletnosc_polon/. Każda reguła sprawdzana parą rekordów (kompletny / z brakiem), plus testy „fallback ratuje" na każdy człon koniunkcji, testy ziarna, zakresu, warunkowości OA, uprawnień i multi-tenanta.

Przy okazji naprawiony flake w fixture'ach: Dyscyplina_Naukowa.kod jest unikalny, a generator model_bakery losuje z wąskiego zakresu — test budujący 28 powiązań trafiał w kolizję urodzinową (reprodukowalne przez --count=40).

Dług techniczny — do osobnego zgłoszenia, NIE naprawiany tutaj

W repo są trzy niezgodne definicje okna ewaluacyjnego:

Miejsce Wartość
ewaluacja_common/const.py ROK_MIN = 2022, ROK_MAX = 2026
ewaluacja_metryki/models.py:114-120 pola rok_min/rok_max, domyślnie 2022 / 2025
ewaluacja_metryki/tasks.py, utils.py rok_min=2022, rok_max=2025 w ośmiu sygnaturach funkcji

ROK_MAX mówi 2026, a metryki liczą do 2025. Rozjazd siedzi w domyślnych argumentach, nie we wspólnej stałej, więc jest niewidoczny. Wraz z otwarciem okna 2026+ każde z tych miejsc jest błędne.

Ten PR dokłada OKNO_EWALUACJI = (2026, 2029) w ewaluacja_common jako źródło prawdy wyłącznie dla nowej aplikacji i celowo nie rusza reszty — zmiana domyślnych lat przestawiłaby wyniki liczenia metryk i slotów, czyli zachowanie niezwiązane z tym zgłoszeniem.

Uwagi wdrożeniowe

  • Brak migracji.
  • Raport na starcie będzie prawie pusty — okno 2026 dopiero się otwiera. Widok jawnie podaje zakres lat i liczbę sprawdzonych powiązań, żeby pustka nie wyglądała jak „wszystko w porządku".
  • Raport zależy od ustawionych w słowniku charakterów formalnych pól rodzaj_pbn i charakter_sloty. Rekordy, dla których ich brak, trafiają do osobnej sekcji „nierozpoznany typ osiągnięcia" z linkiem do słownika — nie znikają po cichu.

Projekt: docs/superpowers/specs/2026-07-25-raport-kompletnosci-polon-2026-design.md

Refs FD#437

🤖 Generated with Claude Code

https://claude.ai/code/session_01McWgJYK4c4GSMdsm6P4oXc

mpasternak and others added 5 commits July 25, 2026 02:02
Rozporządzenie MNiSW z 16.06.2026 (Dz.U. 2026 poz. 811) określa w § 2 ust. 10
zakres danych o osiągnięciach naukowych w wykazie pracowników. Rozpoznanie
wykazało, że BPP ma już prawie wszystkie wymagane pola (pokrywają się z
eksportem do PBN) — brakuje widoczności, które rekordy są niekompletne.

Spec projektuje raport kompletności: ziarno (autor, dyscyplina, rekord) na
konkretnych modelach powiązań, deklaratywny rejestr reguł z odnośnikami do
paragrafów, liczenie na żywo bez materializacji.

Odnotowane braki modelu do osobnych zgłoszeń: ISMN, flaga przekładu, ocena
ekspercka KEN, osiem pól patentowych (por. FD#449), osiągnięcia artystyczne.

Refs FD#437

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01McWgJYK4c4GSMdsm6P4oXc
Fundament raportu: aplikacja bez modeli, deklaratywny rejestr 40 reguł
odwzorowujących § 2 ust. 10 rozporządzenia (Dz.U. 2026 poz. 811) dla
artykułów, monografii, rozdziałów i patentów.

Reguła to dane: kod, typ osiągnięcia, warunek Q prawdziwy gdy danej brakuje,
opis dla użytkownika, paragraf podstawy prawnej i waga (wymagane vs warunkowe
— rozporządzenie w wielu miejscach mówi "jeżeli posiada" / "jeżeli są znane"
i raport tego nie zaostrza).

Warunki zapisane od strony through-modelu powiązania autora z rekordem, nie
od strony publikacji. Zapis odwrotny byłby błędny semantycznie: warunek na
autorzy_set znaczyłby "istnieje jakiś autor bez upoważnienia" zamiast "ten
autor go nie ma", a przy annotate() mnożyłby wiersze przez JOIN. Spec
poprawiony w tym miejscu.

OKNO_EWALUACJI = (2026, 2029) w ewaluacja_common jako źródło prawdy dla tej
aplikacji; istniejące ROK_MIN/ROK_MAX celowo nietknięte.

203 testy: każda reguła sprawdzana parą rekordów (kompletny / z brakiem).

Refs FD#437

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01McWgJYK4c4GSMdsm6P4oXc
powiazania() buduje queryset through-modelu per typ osiągnięcia, zawężony do
okna ewaluacji, powiązań przypiętych i uczelni oglądającego (przez istniejący
scope_autorzy_do_uczelni, nie własny filtr). z_regulami() dokłada po polu
logicznym na regułę plus liczniki braków wymaganych i warunkowych.

Zawężenie NIE odsiewa powiązań bez dyscypliny. Spec mówił o "przypiętej
dyscyplinie", co dosłownie odsiałoby dyscyplina IS NULL — a wtedy reguły
*_DYSCYPLINA nigdy by nie zadziałały i raport przemilczałby brak, o który
pyta. Spec poprawiony.

Wydawnictwa zwarte bez ustawionego charakter_sloty (fixture instalacyjny
zostawia je puste) nie znikają po cichu — powiazania_nierozpoznane() zbiera je
do osobnej sekcji, żeby użytkownik nie uznał ich za sprawdzone.

228 testów (203 z kroku 1 + 25 nowych), zweryfikowane mutacyjnie.

Refs FD#437

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01McWgJYK4c4GSMdsm6P4oXc
Widok zbiorczy listuje autorów posortowanych malejąco po brakach wymaganych;
widok szczegółów wypisuje przy każdym rekordzie naruszone wymogi z podstawą
prawną i linkiem do formularza edycji w adminie.

Dostęp tylko dla redaktorów (ma_pelne_uprawnienia_ewaluacji) — to narzędzie
robocze, nie widok dla autora. Dane zawężone do uczelni oglądającego.

Rekordy z nieustawionym charakter_sloty mają własną sekcję w obu widokach.
Na liście jest ona zagregowana per autor, bo autor mający wyłącznie takie
rekordy nie pojawia się w tabeli głównej i inaczej byłby nieosiągalny.

Kontekst widoku celowo nie wystawia klucza "uczelnia" — nadpisywał wartość
z context processora, której base.html używa do stopki, i przy uczelnia=None
wywracał szablon bazowy. Złapane testem.

249 testów (228 backendu + 21 widoków).

Refs FD#437

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01McWgJYK4c4GSMdsm6P4oXc
Recenzja całości znalazła dwa błędy krytyczne, wyciek danych między
uczelniami i pięć luk wobec rozporządzenia. Rejestr urósł z 40 do 50 reguł.

KRYTYCZNE — wydawnictwa ciągłe nie były filtrowane po charakterze formalnym,
więc streszczenia zjazdowe, listy do redakcji i recenzje były audytowane jako
artykuły naukowe: raport żądał DOI od streszczenia konferencyjnego. Ziarno
zawężone do rodzaj_pbn=RODZAJ_PBN_ARTYKUL, idiomem używanym już w
pbn_integrator i komparator_pbn.

KRYTYCZNE — monografia macierzysta rozdziału nie była sprawdzana nigdy.
Komentarz twierdził, że jej braki widać przy monografii, ale rodzic trafia do
raportu tylko gdy sam ma autora z uczelni; rozdział w monografii zbiorowej pod
obcą redakcją takiego rodzica nie ma. Dodane ROZ_MON_ISBN/WYDAWCA/DOI.

BEZPIECZEŃSTWO — widok szczegółów nie zawężał autora do uczelni. Superuser
mógł podać slug autora obcej uczelni i dostać 200 z jego nazwiskiem; slug jest
przewidywalny, więc pozwalało to enumerować kadrę. Teraz 404.

Dołożone wymogi rozporządzenia: tryb dostępu OA (bez tej reguły rekord z datą
OA, ale bez trybu, wersji i licencji nie dawał żadnego naruszenia), kwota APC
przy zadeklarowanej niebezkosztowości, oraz cała lit. g o konferencjach —
pominięta mimo że BPP ma na nią pola.

Rekordy, których raport nie umie zaklasyfikować, nie znikają po cichu w żadną
stronę: sekcja "nierozpoznany typ" obejmuje teraz i zwarte bez charakter_sloty,
i ciągłe bez rodzaj_pbn, a komunikat kieruje do słownika charakterów, nie do
formularza rekordu.

Paginacja listy (25 autorów) — założenie "zbiór jest mały" nie przeżyje
pierwszego roku okna, bo pola pbn_czy_* i opl_pub_* mają default=None.

Testy 249 -> 341. Dotychczasowy wzorzec zerował wszystkie człony koniunkcji
naraz, więc dowolny fallback dało się usunąć przy zielonej suicie; dołożone
testy na każdy człon. Wszystkie poprawki zweryfikowane mutacyjnie.

Refs FD#437

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01McWgJYK4c4GSMdsm6P4oXc
@gitguardian

gitguardian Bot commented Jul 25, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
35167251 Triggered Generic Password 71539ec src/kompletnosc_polon/tests/test_views.py View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

OKNO_EWALUACJI = (2026, None) zamiast zgadywanego (2026, 2029). MEiN nie
ogłosiło jeszcze, czy nowy okres ewaluacyjny ma cztery czy pięć lat, a
zaszyta granica oznaczałaby, że w 2030 r. raport po cichu przestaje pokazywać
nowe rekordy. None znaczy "granica nieustalona"; domknięcie to jedna liczba.

Okno jest prywatnym ustawieniem raportu POL-on i celowo NIE jest tym samym
zegarem co zakres metryk i liczby N — raport pyta o obowiązek sprawozdawczy
z rozporządzenia, metryki liczą punktację.

Zakres lat pokazywany użytkownikowi przechodzi przez opis_okna(): "od 2026"
przy granicy otwartej, "2026-2029" po domknięciu. Para pierwszy_rok/
ostatni_rok wyleciała z kontekstu szablonu, żeby nie dało się jej skleić w
"2026-None"; pilnuje tego asercja w testach.

348 testów (+7). Weryfikacja mutacyjna: po przywróceniu bezwarunkowego lte
padają testy odległego roku.

Refs FD#437

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01McWgJYK4c4GSMdsm6P4oXc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant