System rezerwacji rzadko jest tylko kalendarzem. W chwili, gdy ktoś rezerwuje termin, przechowujesz jego imię, e-mail, numer telefonu - a w klinice, salonie czy gabinecie terapeutycznym często coś znacznie bardziej wrażliwego: powód wizyty.
Te dane to najcenniejsza rzecz, jaką posiadasz, i jednocześnie najłatwiejsza do utraty. Jedna źle skonfigurowana tabela, jeden wyciekły token, jeden najemca zdolny odczytać dane innego najemcy - i zaufanie budowane latami znika w jedno popołudnie.
Dlatego w Timerise nie traktujemy bezpieczeństwa jako funkcji, którą się włącza. Traktujemy je jako architekturę. Każda warstwa - sieć, baza danych, uwierzytelnianie, szyfrowanie, sekrety, audyt i testy, które to wszystko spinają - zakłada, że warstwa nad nią może zawieść. To jest obrona w głąb (defense in depth), i tak właśnie działa to w naszych produktach rezerwacyjnych.
Przechowywanie danych w UE, na które możesz wskazać
Zgodność zaczyna się od prostego pytania: gdzie fizycznie znajdują się moje dane? Dla klientów europejskich odpowiedź musi brzmieć „w Europie" - bez gwiazdek.
Timerise działa na Google Cloud, Vercel i Supabase - trzech dostawcach niezależnie audytowanych, certyfikowanych według ISO 27001 i gotowych na HIPAA, z których każdy jest zabezpieczony podpisaną umową powierzenia przetwarzania danych. Przypinamy przechowywanie i moc obliczeniową do regionów UE (Frankfurt dla wdrożeń o najwyższych wymaganiach RODO), dzięki czemu dane osobowe pozostają w Europejskim Obszarze Gospodarczym z założenia, a nie przez przypadek.
To znaczy, że gdy klient pyta, gdzie przechowywane są dane jego pacjentów, podajesz region, a nie wzruszasz ramionami. Lokalizacja danych to konfiguracja, którą kontrolujemy, a nie nadzieja, którą żywimy.
Nagłówki bezpieczeństwa w każdej odpowiedzi
Zanim wykona się choćby jeden bajt logiki aplikacji, przeglądarce już powiedziano, jak ma się zachować. Ustawiamy wzmocnione nagłówki bezpieczeństwa HTTP globalnie, w każdej odpowiedzi:
| Nagłówek | Wartość |
|---|---|
Strict-Transport-Security | max-age=63072000; includeSubDomains; preload |
X-Content-Type-Options | nosniff |
X-Frame-Options | DENY |
Referrer-Policy | strict-origin-when-cross-origin |
Permissions-Policy | camera=(), microphone=(), geolocation=() |
Content-Security-Policy | restrykcyjna baza |
HSTS wymusza HTTPS przez dwa lata (i znajduje się na liście preload przeglądarek). X-Frame-Options: DENY oraz Content Security Policy z frame-ancestors 'none' sprawiają, że clickjacking przestaje być zagrożeniem. Baza CSP zaczyna się od default-src 'self' i jest stamtąd zacieśniana - object-src 'none', base-uri i form-action ograniczone do własnego źródła - więc zbiór miejsc, z których strona może wczytać kod lub wysłać formularz, jest mały i jawny.
To nie są przełączniki, o których klient musi pamiętać. Są domyślnie włączone, wszędzie.
Izolacja najemców wymuszana w bazie danych
Większość naruszeń w systemach wielonajemcowych to nie spektakularne exploity. To zapomniane WHERE tenant_id = ? w jakimś zapytaniu napisanym o 2 w nocy. Jedyną niezawodną obroną jest przestać ufać, że kod aplikacji o tym pamięta.
Dlatego izolacja najemców w Timerise mieszka w samej bazie danych - poprzez Row-Level Security (RLS) w Postgresie. Każda tabela z danymi najemcy ma polityki, które czynią wiersz niewidocznym - przy odczycie, zapisie i wstawianiu - dla kogokolwiek spoza jego najemcy. W połączeniu z modelem zapisu server-first (klienci nigdy nie otrzymują bezpośredniej, uprzywilejowanej ścieżki do danych) jeden najemca po prostu nie może zobaczyć ani naruszyć rezerwacji, klientów czy rekordów innego. Baza danych to wymusza - nawet jeśli zapytanie o tym zapomni.
To nie jest twierdzenie, które masz przyjąć na wiarę. Dowodzimy tego przy każdym commicie - o tym za chwilę.
Uwierzytelnianie zbudowane dla wrażliwych zadań
Przy sesjach wygoda i bezpieczeństwo zwykle ze sobą walczą. Rozwiązujemy to za pomocą Supabase Auth i kilku rzeczy niepodlegających negocjacji.
- Wzmocnione ciasteczka. Sesje przenoszone są w ciasteczkach HTTP-only, Secure, SameSite zarządzanych przez
@supabase/ssr- nigdy odczytywalnych przez JavaScript, nigdy wysyłanych między witrynami. - Krótkotrwałe tokeny z rotacją. JWT wygasają po godzinie, a tokeny odświeżające rotują przy każdym użyciu. Skradziony, ponownie użyty token odświeżający jest wykrywany i unieważnia całą rodzinę sesji - wyciekły token to ślepa uliczka, a nie klucz uniwersalny.
- Ograniczona tożsamość. Każde żądanie niesie rolę i najemcę użytkownika, a wiążąca kontrola dostępu działa po stronie serwera na chronionych layoutach - a nie tylko optymistycznie na brzegu sieci.
- Stłumiony brute force. Powtarzające się nieudane logowania uruchamiają throttling i eskalację CAPTCHA; wrażliwe trasy API i uwierzytelniania są ograniczane przepustowo metodą token bucket.
- Silne dane logowania. Hasła muszą mieć co najmniej 12 znaków i są sprawdzane względem baz znanych wycieków w momencie ich ustawiania.
- MFA dla kluczy do królestwa. Uwierzytelnianie wieloskładnikowe TOTP chroni konta właściciela i menedżera - role, które widzą i zmieniają najwięcej.
Szyfrowanie danych medycznych (RODO Artykuł 9)
Dane medyczne to szczególna kategoria danych zgodnie z Artykułem 9 RODO i tak je traktujemy - dedykowanym stosem, a nie odhaczeniem pola.
Pola kliniczne mieszkają we własnym, odizolowanym schemacie clinical i są chronione szyfrowaniem kopertowym po stronie aplikacji: każdy najemca otrzymuje własny klucz szyfrowania danych, a ten klucz sam jest opakowany kluczem głównym przechowywanym w Supabase Vault lub zewnętrznym KMS w UE - nigdy w repozytorium, z udokumentowaną polityką rotacji. Odszyfrowanie odbywa się wyłącznie po stronie serwera; surowe wartości nigdy nie docierają do przeglądarki. Przechowywane kolumny to szyfrogram, bezużyteczny dla kogokolwiek czytającego bazę danych bezpośrednio.
Zdjęcia „przed/po" i inne wrażliwe media mieszkają w prywatnym buckecie, w ogóle bez publicznych adresów URL. Dostęp przyznawany jest wyłącznie przez krótkotrwałe podpisane adresy URL, wydawane po kontroli roli po stronie serwera - więc linku nie da się zgadnąć, pobrać masowo ani udostępnić po jego wygaśnięciu.
Sekrety, które nigdy nie dotykają repozytorium
Najszybszy sposób, by wyciekło wszystko, to scommitować klucz. Utrudniamy zrobienie tego przez przypadek.
Sekrety żyją wyłącznie w środowisku platformy (Vercel env), nigdy w kodzie; .env.local jest w gitignore i pobierany na żądanie. gitleaks skanuje w poszukiwaniu danych uwierzytelniających zarówno w CI, jak i jako hook pre-commit, więc przypadkowy klucz zostaje wychwycony, zanim w ogóle trafi na zdalną gałąź. Klucze szyfrujące, jak wspomniano wyżej, leżą w vaulcie lub KMS - całkowicie oddzielone od aplikacji.
Każde wrażliwe działanie jest audytowane
Gdy jednak coś pójdzie nie tak - albo gdy klient, regulator lub audytor zapyta „kto dotknął tego rekordu?" - potrzebujesz odpowiedzi, a nie domysłu.
Każda zmiana danych klinicznych i finansowych zapisuje wiersz w dzienniku audytu tylko do dopisywania (append-only): kto to zrobił (aktor), kiedy (znacznik czasu), co (encja) oraz różnicę przed/po dokładnie tego, co się zmieniło. Odczyty rekordów klinicznych również są rejestrowane, ponieważ w kontekście medycznym samo spojrzenie jest zdarzeniem regulowanym. Dziennik jest z założenia tylko do dopisywania - wpisy można zapisać, ale nigdy po cichu edytować ani usunąć.
Udowodnione, nie obiecane: pełne pokrycie testami
Obietnice bezpieczeństwa są bezwartościowe, jeśli po następnym refaktorze nic ich nie sprawdza. Dlatego powyższe mechanizmy nie są udokumentowane i zapomniane - są testowane, a testy bramkują każde wdrożenie.
- Testy jednostkowe z wymuszonym pokryciem. Vitest z pokryciem v8 utrzymuje próg 80% dla naszego rdzennego kodu bibliotecznego, w tym warstwy szyfrowania - poprawność cyklu round-trip, izolacja kluczy najemców i wykrywanie manipulacji (zmodyfikowany szyfrogram musi odmówić odszyfrowania).
- Macierz izolacji. Testy integracyjne działają na prawdziwym Postgresie, a nie na mockach, i sprawdzają to, co najważniejsze: najemca A nigdy nie może odczytać, zapisać ani wstawić wierszy najemcy B, a dziennik audytu pozostaje tylko do dopisywania. Równoległa macierz kliniczna dowodzi, że rekordy szczególnej kategorii są widoczne dla ról klinicznych i ukryte przed recepcją - oraz że przechowywane kolumny to faktyczny szyfrogram.
- Ścieżki dymne end-to-end. Playwright przy każdym wdrożeniu przechodzi prawdziwe przepływy rezerwacji, z automatycznymi kontrolami dostępności (Axe), które wywalają build przy poważnych lub krytycznych naruszeniach.
- Testy obciążeniowe. Cotygodniowe przebiegi k6 utrzymują szybkość gorących ścieżek pod presją, bo dostępność to też część bezpieczeństwa.
Lintowanie, sprawdzanie typów oraz dedykowany linter polityk RLS także bramkują CI. Zmiana osłabiająca izolację nie dostaje surowego code review - dostaje czerwony build.
Co to oznacza dla RODO, ISO i HIPAA
Frameworki nie zabezpieczają systemów; robią to mechanizmy kontrolne. Ale warto zobaczyć, jak się to mapuje:
- RODO. Przechowywanie danych w UE, szyfrowanie kopertowe zgodnie z Artykułem 9 dla danych medycznych, kompletny ślad audytowy, minimalizacja danych na poziomie bazy oraz podpisane umowy powierzenia z każdym podprocesorem.
- ISO 27001. Budujemy na infrastrukturze z certyfikatem ISO 27001 i odzwierciedlamy jej dyscyplinę w praktyce - dostęp na zasadzie najmniejszych uprawnień, zarządzanie sekretami, kontrola zmian bramkowana przez CI oraz przetestowana izolacja.
- HIPAA. Platforma działa na infrastrukturze gotowej na HIPAA z technicznymi zabezpieczeniami, których wymagają regulowane dane medyczne: szyfrowanie w spoczynku i w tranzycie, ścisła kontrola dostępu oraz audytowany dostęp do chronionych rekordów.
Nie wręczamy Ci oprawionego w ramkę certyfikatu i nie kończymy na tym. Wręczamy Ci architekturę - i testy, które wciąż na nowo dowodzą, że nadal jest prawdziwa.
Podsumowanie
Bezpieczeństwo w Timerise to nie ustawienie; to sposób, w jaki produkt jest zbudowany. Przechowywanie danych w UE, wzmocnione nagłówki, wymuszana w bazie izolacja najemców, krótkotrwałe rotujące sesje z MFA, dane medyczne szyfrowane kopertowo, sekrety trzymane w vaulcie, dzienniki audytu tylko do dopisywania - i pakiet testów, który wywala build w chwili, gdy cokolwiek z tego zaczyna się sypać.
Dane Twoich klientów to najbardziej wrażliwa rzecz, jaką kiedykolwiek dla nich przechowasz. Buduj na fundamencie, który tak je traktuje.
Przeczytaj naszą dokumentację bezpieczeństwa i prywatności →
Sprawdź naszą umowę powierzenia, politykę prywatności i regulamin →
<br>Porozmawiaj z nami o swoim systemie rezerwacji
Bez sprzedażowego skryptu. Powiedz nam, co budujesz, a my powiemy, jak byśmy to zbudowali.
Czytaj też
Proste API do rezerwacji: Przewodnik dla początkujących
Dla firm zarządzających spotkaniami, wydarzeniami lub wynajmem, sprawny system rezerwacji jest niezbędny. Niezależnie od tego, czy jesteś właścicielem małej firmy, czy programistą...
API rezerwacji ze strefami czasowymi: Dla agentów AI i custom frontendów
Agenci AI potrzebują precyzyjnej obsługi stref czasowych do rezerwacji międzynarodowych. Zobacz, jak Timerise GraphQL API używa UTC-first, IANA i DateTimeISO.