← Portfolio Case Study

Studio Manager — gdy jedna poprawka ujawnia 11 ukrytych

Klient: Studio usługowe ze Szwajcarii (klient stały) Czas: 1 dzień roboczy (7. projekt w cyklu 3-miesięcznym)
Base44 Deno Deploy Webhooks Resend Compliance

Przed

  • Mail do urzędu nie wychodził dla nowo utworzonych profili
  • Pole statusu puste (null) — UI renderował to jak „nie odwiedziła"
  • 11 historycznych rekordów z tym samym problemem (klient znał 4)
  • Testy przez agenta AI platformy dawały false negatives

Po

  • 5 punktów scope dostarczonych + 50% odkrytego scope ekstra
  • 11 rekordów historycznych wyciągniętych do ręcznego przeglądu
  • Auto-default + dedykowana sekcja UI dla pustych statusów
  • Naprawione 2 bugi platformy + zmieniona metodologia testów

Kontekst: 7. projekt w cyklu 3 miesięcy

Klient prowadzi studio usługowe w Szwajcarii. System zarządzania zbudowany na platformie low-code (Base44) plus własne webhooks na Deno Deploy. Pracujemy razem od trzech miesięcy — relacja zaczęła się od jednej małej naprawy (zerwana integracja z Telegramem) i rozrosła się do siedmiu kolejnych projektów, każdy w fixed-price.

Wcześniejsze fazy: parowanie bota, zabezpieczenie wypłat (atomowość operacji), 3-poziomowe RBAC, drugi sklonowany system dla drugiej lokalizacji, osobny bot powiadomień, refaktor logiki wypłat z przeglądarki na backend. Ten case study to faza 7 — integracja maila compliance.

Powracający wzorzec: stany UI, które wyglądają jak odpowiedzi, ale nie są. Ten bug to klasyczny przykład.

Problem

Klientka zgłosiła precyzyjnie: niedawno dezaktywowana pracownica z 90-dniowym pozwoleniem nie wygenerowała spodziewanego maila compliance do urzędu zewnętrznego. W panelu jej status wyglądał jak „nie odwiedziła" — czyli warunek wysłania maila. W rzeczywistości pole było puste (null), a automatyzacja odpalała się tylko na jawne "not_visited".

Honest framing: to była luka w mojej własnej implementacji sprzed dwóch tygodni. Zaprojektowałem ścieżkę dla jawnego "not_visited" i nie pomyślałem, że pole może być puste — a takie było dla każdego nowo utworzonego profilu, dopóki ktoś nie kliknął przycisku w panelu. Naprawę zaabsorbowałem w cenie pierwotnego projektu jako warranty.

Diagnoza

Bug to góra lodowa. Pierwszy obiecany scope miał 5 punktów. Po wdrożeniu pierwszej zmiany (sekcji UI dla profili z pustym statusem) panel sam wyrenderował 11 historycznych rekordów z tym samym problemem. Klientka znała 4. System znalazł 14.

Po drodze wyszło dodatkowo:

  • 3 wcześniej nieznane nowe profile utworzone w dniach przed pojawieniem się buga — ten sam pusty status, ten sam problem.
  • Bug platformy: operator is_empty nie matchował null, tylko pustych stringów. Pierwsza automatyzacja auto-default nie odpalała się w testach.
  • Bug klasyfikatora UI: dziedziczony fallback w panelu (return 'not_visited') maskował puste pola jako „nie" — ten sam mechanizm, który ukrył oryginalnego buga.
  • Odkrycie warte złota: testy end-to-end przez agenta AI platformy (server-role) nie triggerują automatyzacji entity. Tylko operacje user-context. To wyjaśniło kilka wcześniejszych dziwnych wyników testów i zmieniło moją metodologię.

Rozwiązanie

1. Filtr funkcji mailowej

Przepisany filtr akceptuje null i pusty string jako „nie odwiedziła" — pod warunkiem, że pozwolenie to 90-dniowe. Dwa stany prawdy: jawne i implicite.

2. Auto-default na nowych profilach

Automatyzacja inicjalizuje pole statusu na "not_visited" w momencie utworzenia profilu z 90-dniowym pozwoleniem. Pole nigdy więcej nie jest puste „przypadkiem".

3. Nowa sekcja UI

Dedykowana sekcja w panelu dla profili z pustym statusem, z odrębnym kolorem. Klient widzi, co system nie wie, a nie tylko to, co system wie. Fix na poziomie wizualnym + naprawa klasyfikatora w kodzie panelu.

4. Migracja danych historycznych

14 zidentyfikowanych rekordów wyciągniętych do ręcznego przeglądu klienta — case-by-case, nie auto-resolve. Klient sam decyduje, co z każdym przypadkiem.

5. End-to-end test przez prawdziwą ścieżkę

Test wykonany przez interfejs jak realny użytkownik (utworzenie profilu testowego, dezaktywacja, weryfikacja maila compliance). Pass.

Efekt

Klient zapłacił cenę pierwotnego projektu. Otrzymał:

  • 5 obiecanych punktów scope, wszystkie działają
  • 3 wcześniej nieznane profile poprawnie zainicjalizowane jako efekt due diligence
  • 11 historycznych rekordów wyciągniętych do przeglądu (nie auto-resolve — to jego decyzja)
  • 2 bugi platformy znalezione i obejście / eskalacja do AI platformy
  • Bug UI klasyfikatora poza explicit scope, ale konieczny żeby nowa sekcja w ogóle miała sens

Realny czas: ~2,5x szacunku dla pierwotnych 5 punktów. Część to warranty na moim wcześniejszym kodzie. Reszta to discovery — rzeczy, których nie było na liście, ale bez których lista by nic nie znaczyła.

Wnioski

Pięć lekcji, które zabieram z tego projektu do każdej kolejnej fixed-price:

  1. Stany UI, które wyglądają jak odpowiedzi, ale nie są, to fundamentalne ryzyko jakości danych. Naprawa wymaga zmian na trzech warstwach: model danych (inicjalizacja), klasyfikator UI (rozróżnienie pustego od „nie"), prezentacja wizualna (osobna sekcja). Sam jeden poziom nie wystarcza.
  2. End-to-end znaczy end-to-end — przez tę samą ścieżkę wykonania, którą używają realni użytkownicy. Pół dnia zmarnowane na testach przez kanał, który nie odpalał automatyzacji.
  3. Discovery rider w każdym fixed-price. Analiza zawsze niedoszacowuje scope, bo problemy z jakością danych wychodzą dopiero gdy system zaczyna ich szukać. Następne kontrakty będą miały zdanie: „jeśli analiza ujawni dodatkowe rekordy lub systemowe problemy poza listą, będą wycenione osobno".
  4. Warranty to warranty — nazywać po imieniu. Absorbcja rework w cenie pierwotnej to świadomy wybór, nie milczące rozszerzenie zakresu. Komunikować jasno.
  5. Korespondencja klienta to source of truth. Każda reguła biznesowa w tym projekcie sięgała do konkretnego cytatu z wiadomości klienta — czasem sprzed dwóch miesięcy. Nie zgadywać tam, gdzie można sprawdzić.

Trzy miesiące pracy z tym klientem to najcenniejszy aktyw tej współpracy. Ten projekt jest przykładem, gdzie wybrałem zaabsorbować dodatkowy koszt w zamian za czystą dostawę i kontynuację relacji. Zrobiłbym to samo jeszcze raz — ale następnym razem komunikuję trade-off jaśniej.

Masz podobny problem?

Opisz go AI — zbierze kontekst techniczny, Artur przygotuje wycenę w 48h.

Rozpocznij diagnostykę