Panel Directusa intranetu: rejestr przyjęć odpadów PSZOK i Centralny Rejestr Umów, z drzewem modułów po lewej

Programowanie

Intranet urzędu: Directus dziś, NocoBase jutro

Wspólna baza Urzędu Miejskiego w Starym Sączu: 136 kolekcji, od kadr i czasu pracy po PSZOK i rejestr umów. Dlaczego licencja Directusa wymusza przesiadkę, jak wybrałem następcę na prototypie i jak będzie wyglądał nowy intranet.

18.10.2026

Intranet Urzędu Miejskiego w Starym Sączu to system, którego mieszkańcy nigdy nie zobaczą, a od którego zależy sporo usług, z których korzystają. Z niego biorą dane tablice w holu, ewidencja PSZOK, rejestracja czasu pracy, generator podpisów i wydruki protokołów.

Działa na Directusie, czyli panelu do zarządzania danymi zbudowanym na zwykłej bazie SQL. Przez kilka lat urósł do kilkunastu modułów. Teraz przygotowuję jego następcę i opisuję, dlaczego.

Panel Directusa intranetu: rejestr przyjęć odpadów PSZOK i Centralny Rejestr Umów, z drzewem modułów po lewej
Panel intranetu. Na zrzutach lokalna kopia z danymi fikcyjnymi

Co jest w środku

Intranet to w praktyce wspólna baza urzędu z panelem do jej obsługi. Ma 136 kolekcji z danymi, ponad 1500 pól, prawie 400 relacji i kilkanaście tysięcy plików. Najważniejsze moduły:

  • Zarządzanie jednostką: pracownicy, struktura wydziałów i referatów, stanowiska, zakresy czynności, karty dostępu i identyfikatory,
  • Czas pracy: odbicia z czytnika kart, dzienne obecności, korekty i wnioski kadrowe,
  • Ochrona danych osobowych: rejestr czynności przetwarzania, systemy, upoważnienia, analiza ryzyka,
  • PSZOK i system śmieciowy: wizyty, rodzaje odpadów, limity, deklaracje, kody kreskowe,
  • Informatyka: komputery, oprogramowanie i licencje, dostępy, urządzenia mobilne i karty SIM,
  • Finanse i majątek: budżet, wydatki, zamówienia publiczne, inwentaryzacja,
  • Rejestry wspólne: Centralny Rejestr Umów z plikami, kontrahenci, karta mieszkańca,
  • Baza inwestycji publikowana na portal gminy, obsługa Rady Miejskiej i OSP,
  • Ekrany i kioski: slajdy, pokoje i komunikaty dla tablic w holu,
  • Helpdesk, FAQ i ustawienia bramki SMS.
Mapa modułów intranetu z liczbą kolekcji: zarządzanie jednostką, czas pracy, ochrona danych, PSZOK i odpady, informatyka, finanse i majątek, rejestry wspólne, inwestycje, Rada Miejska, OSP, ekrany i kioski, helpdesk i SMS
Moduły intranetu i liczba kolekcji w każdym

Wokół intranetu

Większość moich systemów dla urzędu korzysta z intranetu przez API. Każdy z własnym kontem i własnym zakresem uprawnień:

  • importer RCP zapisuje odbicia z czytnika kart, a aplikacja kadrowa pokazuje z nich obecności,
  • system PSZOK czyta deklaracje i zapisuje wizyty,
  • generator podpisów bierze dane pracownika i ustawienia urzędu,
  • tablice w holu pobierają listę pokoi,
  • własne rozszerzenie generuje PDF-y z szablonów, na przykład protokoły PSZOK, przez Gotenberg.

Co trzeba było uporządkować

Intranet rósł latami, dokładany po kawałku, w miarę potrzeb kolejnych referatów. Analiza schematu pokazała typowe skutki takiego wzrostu:

  • foldery w panelu nie odpowiadały dziedzinom, a kilkanaście kolekcji nie miało folderu wcale,
  • trzy różne style nazw kolekcji, pola numerowane przez generator i literówki utrwalone w schemacie,
  • statusy treści CMS, takie jak „opublikowany”, w rejestrach, w których nic się nie publikuje,
  • konto użytkownika i pracownik jako dwa osobne byty, więc zakresu „mój wydział” nie dało się wyrazić prosto,
  • uprawnienia tworzone doraźnie w panelu, bez wzoru ról.

Zrobiłem też przegląd bezpieczeństwa API: kto ma dostęp do czego, które konta usług mają za szerokie uprawnienia i co jest dostępne bez logowania. Uprawnienia zostały uszczelnione, a każda usługa dostaje własne konto z minimalnym zakresem.

Model danych w ustawieniach Directusa: zagnieżdżone foldery i kolekcje
Model danych intranetu w ustawieniach Directusa

Problem z licencją

Directus przez lata był otwarty. Od wersji 10 działa na licencji BSL 1.1. Jest darmowy tylko dla organizacji z budżetem poniżej 5 milionów dolarów rocznie. Gmina przekracza ten próg kilkukrotnie, więc formalnie potrzebuje licencji komercyjnej.

Panel sam o tym przypomina. Po aktualizacji przy każdym logowaniu pojawia się okno z prośbą o wskazanie właściciela projektu i akceptację licencji. Wersja 12 idzie dalej: w darmowej edycji Core pozwala na 3 użytkowników i 25 kolekcji. Intranet ma ich 136 i kilkudziesięciu użytkowników.

Okno Directusa wymagające wskazania właściciela projektu i akceptacji licencji BSL 1.1, z informacją o darmowym użyciu poniżej 5 milionów dolarów budżetu
Przypomnienie o licencji BSL w panelu Directusa

Dla urzędu to nie jest drobna formalność. Płatna licencja na system, z którego korzysta kilka innych aplikacji, wiąże budżet na lata, a zmiana warunków przez dostawcę może się powtórzyć. To dokładnie ten rodzaj zależności, od którego chciałem urząd uwolnić.

Wybór następcy

Zamiast wybierać z opisów, zbudowałem prototyp. Pięć narzędzi dostało te same dane fikcyjne: 100 pracowników, 44 referaty, 3000 mieszkańców i 1500 wizyt PSZOK. Każde dostało też te same cztery role: kadry, kierownika, ewidencję i zwykłego urzędnika.

  • Mathesar, z uprawnieniami egzekwowanymi w PostgreSQL przez RLS,
  • Teable i Grist, arkuszowe bazy danych,
  • NocoBase, platforma no-code z rolami, zakresem rekordów i listą pól,
  • Frappe, framework, na którym stoi ERPNext.

Sprawdzałem przez API, czy każda rola widzi dokładnie to, co powinna. Kierownik tylko swój referat, ewidencja pełne dane mieszkańców, reszta tylko widok z maską numeru PESEL. Wygrał NocoBase. Licencja Apache-2.0 pozwala na użytek wewnętrzny, a wersja darmowa ma role z zakresem rekordów, workflow, import i eksport oraz API.

Próbna migracja Centralnego Rejestru Umów, czyli 2711 umów, 137 kontrahentów, 300 plików PDF i uprawnień, trwała skryptem około 10 sekund. Wartości zgadzały się co do grosza, a relacje wskazywały te same rekordy.

Porównanie obecnego intranetu na Directusie z planowanym na NocoBase i Astro oraz kolejność przenoszenia modułów
Plan przesiadki z Directusa na NocoBase

Jak będzie wyglądał nowy intranet

Nowy intranet to nie kopia starego na innym silniku. Kilka zasad, które ustaliłem przed pierwszą linijką kodu:

  • rdzeń zawsze włączony (organizacja, pulpit, słowniki, ochrona danych, ustawienia) i moduły włączane według potrzeb,
  • schemat, role i klasy danych osobowych jako kod w repozytorium, a panel tylko do pracy i podglądu,
  • każde pole ma klasę danych już w definicji modułu, z której wynika maskowanie, eksport i retencja,
  • pracownik powiązany 1:1 z kontem, więc „mój wydział” to prosty filtr,
  • intranet nie przechowuje numerów PESEL. Mieszkańca wyszukuje się przez łącznik z systemem dziedzinowym, a w intranecie zostaje tylko to, co potrzebne,
  • wszystko, z czego korzysta ktoś spoza urzędu, na przykład OSP czy głosowania mieszkańców, to osobna aplikacja z własną bazą.

Urzędnicy nie będą pracować w panelu administracyjnym. Dostaną własny front w Astro, zgodny z WCAG 2.2, z paskiem dostępności i tym samym wyglądem co portal gminy. Front rozmawia z NocoBase tokenem zalogowanego użytkownika, więc zakres danych i ukryte pola egzekwuje backend, a nie przeglądarka.

Ekran logowania nowego frontu intranetu z paskiem dostępności
Logowanie do nowego intranetu

Przesiadka moduł po module

Nowy intranet startuje obok starego. Moduły przechodzą po kolei, z jednokierunkową synchronizacją danych przed przełączeniem. Directus zostanie wyłączony, gdy nie będzie w nim już żadnego aktywnego modułu.

  • słowniki i struktura organizacyjna,
  • Centralny Rejestr Umów,
  • PSZOK i system śmieciowy,
  • kadry i czas pracy,
  • pozostałe moduły,
  • wyłączenie Directusa.

Pliki trafiają do własnego magazynu S3 na RustFS, miniatury generuje imgproxy, a dokumenty PDF, XLSX i CSV osobna usługa wydruków. Logowanie docelowo przejdzie na Authentik, wspólny dla wszystkich systemów urzędu.

Najdroższy system to nie ten, za który płaci się licencję. To ten, którego nie da się zmienić, bo wszystko inne jest do niego przyspawane.

- Aleksander Kowal

Stack

  • dziś: Directus 11, MySQL 8, Redis, Gotenberg, własne rozszerzenie do PDF,
  • jutro: NocoBase 2 na PostgreSQL 16, RustFS (S3), imgproxy,
  • front dla urzędników: Astro 7 SSR, TailwindCSS v4, DaisyUI v5, WCAG 2.2 AA,
  • logowanie: Authentik (OIDC),
  • Docker, OneDev CI, wdrożenie z tagu wersji.