Panel sztabowy

Wewnętrzny panel sztabowy spinający klientów VulCode i Aphrodi w jednym miejscu. Flagi na kontach, portfele, program partnerski, audyt i rozliczenia - z uprawnieniami zawężonymi per marka. Jedno źródło prawdy dla całego zespołu obsługi.

Panel sztabowy
TL;DR

Jeden pulpit dla całego zespołu obsługującego VulCode i Aphrodi. Uprawnienia są zawężone per marka, więc pracownik jednej marki nie zobaczy klientów drugiej, a każda wrażliwa operacja zostawia ślad w logu audytowym. Zamiast dwóch osobnych paneli - jeden rdzeń API, do którego dołożenie kolejnej marki to konfiguracja, a nie nowy projekt.

Wprowadzenie

Kiedy prowadzisz jedną markę, panel wewnętrzny jest prosty: jeden zespół, jeden zbiór klientów, jedne reguły. Kiedy marek jest dwie, a docelowo więcej, sprawa robi się podchwytliwa. Najłatwiej postawić drugi panel obok pierwszego, ale wtedy te same konta, te same portfele i te same reguły prowizji utrzymujesz podwójnie, a każda poprawka musi trafić w dwa miejsca, bo inaczej wersje się rozjadą.

Panel sztabowy to nasza odpowiedź na to napięcie. Jeden pulpit spina klientów VulCode i Aphrodi, obsługiwanych z jednego widoku, ale z twardą granicą: pracownik przypisany do jednej marki nie widzi klientów drugiej. Do tego dochodzi rzecz, o którą prędzej czy później pyta każdy zespół obsługi: kto i kiedy zmienił tę flagę na koncie. Ten case study jest o tym, jak pogodziliśmy wspólny rdzeń z rozdzieleniem, które musi trzymać naprawdę, a nie tylko wyglądać.

Dwa razy ta sama robota

Obsługa dwóch marek z dwóch osobnych paneli wygląda niewinnie, dopóki nie policzysz, ile rzeczy powtarza się między nimi. Model klienta jest ten sam. Portfel jest ten sam. Program partnerski i reguły prowizji są te same. Faktury, flagi na kontach, logika uprawnień - wszystko to samo, tylko w dwóch kopiach, które ktoś musi trzymać w zgodzie ręcznie.

To nie jest tylko podwójna praca, to podwójna szansa na błąd. Poprawka reguły prowizji wchodzi do jednego panelu, a do drugiego już nie, bo ktoś zapomniał. Nowe pole na koncie klienta pojawia się w jednej marce i znika w drugiej. Im dłużej to żyje, tym bardziej dwie kopie się od siebie oddalają, aż w końcu nie da się powiedzieć, która jest tą właściwą.

Postanowiliśmy więc, że rdzeń jest jeden. Klienci obu marek siedzą w jednym zapleczu, na jednym modelu danych, obsługiwani przez jedno API. Różnicę robi nie osobny kod, tylko zakres uprawnień nałożony na wspólną całość.

Uprawnienia, które kończą się na granicy marki

Sercem tego panelu jest kontrola dostępu zawężona per marka. Rola pracownika nie jest globalna. Jest przypisana do konkretnej marki, a zakres jego uprawnień kończy się dokładnie na granicy tej marki. Ktoś z zespołu VulCode widzi klientów VulCode i tylko ich, mimo że fizycznie siedzą oni w tym samym zapleczu co klienci Aphrodi.

Kluczowe jest to, gdzie ta granica jest sprawdzana. Gdyby zawężenie było tylko filtrem w interfejsie, dałoby się je obejść, dopisując cudze id do adresu. Dlatego sprawdzenie zakresu siedzi na wejściu do API i odrzuca żądanie, zanim dotknie ono danych, niezależnie od tego, co pokazuje albo chowa front.

brandScope.ts · ts
function assertBrandScope(actor: StaffUser, brand: BrandId): void {
  if (!actor.brands.includes(brand)) {
    throw new ForbiddenError('brand out of scope');
  }
}
i
Informacja

Zawężenie per marka nie jest filtrem w interfejsie, który da się obejść, dopisując id do adresu. Sprawdzenie zakresu jest wołane na każdej wrażliwej operacji po stronie API i odrzuca żądanie, zanim dotknie danych. Front może się mylić w tym, co pokazuje; API nie ma prawa się pomylić w tym, co przepuszcza.

Kto zmienił tę flagę i kiedy

W panelu, w którym da się oznaczyć konto, zmienić stawkę prowizji albo poruszyć saldem portfela, pytanie "kto to zrobił" pada nieuchronnie. Bez odpowiedzi zostaje zgadywanie po fakcie i szukanie winnego po pamięci, co jest i niesprawiedliwe, i bezużyteczne.

Dlatego każda wrażliwa akcja zapisuje się w logu audytowym: kto ją wykonał, czego dotyczyła i kiedy się wydarzyła. To nie jest dziennik techniczny dla programistów, tylko czytelny ślad dla zespołu obsługi. Kiedy pada pytanie o zmianę na koncie, odpowiedź jest w logu, a nie w niczyjej głowie.

Ten sam mechanizm pełni drugą, cichszą rolę. Świadomość, że każda operacja zostawia ślad, sama w sobie porządkuje pracę. Nie chodzi o podejrzliwość, tylko o to, że w zespole obsługującym cudze pieniądze przejrzystość jest warunkiem zaufania, a nie dodatkiem.

Jeden rdzeń, wiele marek

Cała ta konstrukcja opiera się na jednym rozdzieleniu: co jest wspólne, a co osobne. Wspólny jest rdzeń, czyli API, model danych, konta i portfele klientów oraz log audytowy. Osobny jest tylko zakres uprawnień i wynikająca z niego widoczność klientów. Nic więcej nie musi się rozgałęziać.

Konsekwencja tego podziału jest praktyczna i wieloletnia. Dołożenie kolejnej marki do panelu sztabowego to konfiguracja zakresu, a nie kolejny panel do zbudowania i utrzymania. Nowa reguła prowizji, nowe pole na koncie, nowa operacja - wszystko to wchodzi raz, do wspólnego rdzenia, i od razu obowiązuje wszędzie, tyle że każdy widzi je w granicach swojej marki.

Co jest wspólne, a co osobne

ElementWspólny rdzeńPer marka
API i model danychtak-
Konta i portfele klientówtak-
Reguły prowizji i portfeletak-
Log audytowytak-
Zakres uprawnień-tak
Widoczność klientów-tak

Panele do utrzymania przy dwóch markach (orientacyjnie)

Dwa osobne panele
2
Jeden rdzeń z zakresami
1

Jaki jest finalny efekt?

Zespół pracuje z jednego miejsca, a nie z dwóch przeglądarkowych zakładek, które trzeba trzymać w głowie i pilnować, żeby się nie rozjechały. Klienci obu marek są tam, gdzie mają być, każdy pracownik widzi dokładnie swój wycinek, a granica między markami trzyma na poziomie API, a nie na dobrej woli interfejsu.

Kiedy pada pytanie o zmianę na koncie, odpowiedź jest w logu audytowym, a nie w niczyjej pamięci ani w domysłach. To zamienia rozmowy typu "kto to zrobił" z konfliktu w zwykłe sprawdzenie faktu, co w zespole obsługującym cudze pieniądze jest różnicą między zaufaniem a ciągłym napięciem.

Najważniejsze jest jednak to, że architektura jest gotowa na przyszłość. Dorzucenie trzeciej marki nie oznacza trzeciego panelu, tylko kolejny zakres na tym samym rdzeniu. Rozwój zaplecza nie mnoży się przez liczbę marek, bo wspólne zostaje wspólne, a osobne ogranicza się do tego, co naprawdę musi być osobne.

Więcej projektów

Inne realizacje z tej samej kategorii - zobacz, jak podchodzimy do podobnych wyzwań.

Masz podobny projekt?

Napisz do nas - wycena jest bezpłatna i wraca w godzinę.