Przejdź do głównej zawartości

Projektowanie systemów z Cursor Agent

Twój startup właśnie pozyskał pierwszego klienta korporacyjnego. Chcą izolacji danych w modelu multi-tenant, 99,9% uptime, logowania audytowego, kontroli dostępu opartej na rolach i integracji z ich dostawcą SSO. Twoja obecna architektura — pojedyncza aplikacja Next.js z bazą PostgreSQL — bez problemu obsługuje 500 istniejących użytkowników, ale nie była projektowana z myślą o żadnym z tych wymagań. Musisz przeprojektować kluczowe części systemu bez przepisywania od zera i podjąć decyzje dotyczące multi-tenancy, izolacji danych i architektury uwierzytelniania, które będą cię albo wspierać, albo ograniczać przez lata.

Projektowanie systemu to jedna z najważniejszych czynności, które wykonuje programista, i jedna z najtrudniejszych do zrobienia dobrze. Każda decyzja ma kaskadowe konsekwencje: wybór izolacji na poziomie wierszy vs schemat-per-tenant wpływa na warstwę zapytań, strategię migracji, postawę compliance i złożoność operacyjną. Tryby Plan i Ask w Cursor są stworzone dokładnie do tego rodzaju eksploracyjnej pracy wymagającej wielu decyzji — gdzie musisz pomyśleć, zanim zaczniesz budować.

  • Workflow do używania trybu Plan w celu tworzenia propozycji architektonicznych przed pisaniem kodu
  • Prompty do oceny kompromisów między konkurującymi podejściami projektowymi
  • Strategię generowania Architecture Decision Records (ADR) z Cursor
  • Techniki przekształcania wysokopoziomowej architektury w konkretne plany implementacji
  • Reguły projektu, które kodyfikują decyzje architektoniczne, dzięki czemu Agent egzekwuje je w kodzie

Dla każdej decyzji architektonicznej, która dotyczy więcej niż jednego serwisu lub wykracza poza pojedynczy sprint, zacznij w trybie Plan. Tryb Plan przeszukuje twój codebase, zadaje pytania uściślające i tworzy ustrukturyzowany plan — wszystko przed dotknięciem jakiegokolwiek pliku.

Tryb Plan przeskanuje schemat bazy danych, zbada implementację uwierzytelniania, przejrzy trasy API, a następnie zada celowane pytania: “Czy potrzebujesz izolacji bazy danych na poziomie tenanta ze względu na compliance, czy wystarczy izolacja na poziomie wierszy? Czy twoi klienci korporacyjni wymagają przechowywania danych w konkretnych regionach?”

Ta wymiana pytań i odpowiedzi to najcenniejsza część. AI wyłania pytania, o których mógłbyś nie pomyśleć, a twoje odpowiedzi kształtują propozycję.

Decyzje architektoniczne zawsze wiążą się z kompromisami. Tryb Ask to odpowiednie narzędzie do ich eksplorowania, ponieważ jest tylko do odczytu — bez ryzyka przedwczesnej implementacji.

@scripts/schema.sql
Muszę wybrać podejście do multi-tenancy. Oto opcje, które rozważam:
Opcja A: Izolacja na poziomie wierszy
- Dodanie kolumny tenant_id do każdej tabeli
- Polityki Row-Level Security (RLS) w PostgreSQL
- Wszyscy tenanci współdzielą jedną bazę danych
Opcja B: Schemat-per-tenant
- Każdy tenant dostaje własny schemat PostgreSQL
- Współdzielona pula połączeń, oddzielne przestrzenie nazw
- Migracje uruchamiane per schemat
Opcja C: Baza-danych-per-tenant
- Każdy tenant dostaje własną bazę danych
- Pełna izolacja, ale operacyjnie złożone
- Wyższy koszt infrastruktury
Biorąc pod uwagę nasz obecny schemat z 50 tabelami, przeanalizuj:
1. Nakład migracyjny dla każdej opcji (ile plików się zmieni?)
2. Wpływ na złożoność zapytań (czy musimy zmienić każde zapytanie?)
3. Obciążenie operacyjne (backup, przywracanie, monitoring per tenant)
4. Implikacje wydajnościowe (pooling połączeń, strategie indeksów)
5. Postawa compliance (która opcja spełnia wymóg "izolacji danych"?)
6. Koszt przy 100 tenantach vs 1000 tenantów

Tryb Ask da ci gruntowną analizę bez generowania żadnego kodu. Podejmujesz decyzję na podstawie swoich konkretnych ograniczeń, a następnie przechodzisz do implementacji.

@src/lib/auth @src/pages/api/auth
Musimy dodać SSO (SAML 2.0 i OIDC) do naszego istniejącego uwierzytelniania e-mail/hasło.
Obecna implementacja:
- Tokeny JWT przechowywane w cookies httpOnly
- Niestandardowe middleware auth na trasach API
- Tabela użytkowników z kolumnami email, hashed_password
- Brak koncepcji dostawców tożsamości
Pytania projektowe:
1. Czy powinniśmy zbudować SSO samodzielnie, czy użyć dostawcy auth (Auth0, Clerk, WorkOS)?
2. Jak obsługujemy użytkowników, którzy istnieją z e-mailem/hasłem, a potem ich organizacja włącza SSO?
3. Czy JIT (Just-In-Time) provisioning powinien automatycznie tworzyć użytkowników przy pierwszym logowaniu SSO?
4. Jak obsługujemy przypadek, gdy jedna osoba należy do wielu organizacji?
5. Co się dzieje z aktywnymi sesjami, gdy admin organizacji odbiera użytkownikowi dostęp?
Dla każdego pytania podaj kompromisy 2-3 podejść.
Nie rekomenduj jeszcze rozwiązania -- chcę najpierw zrozumieć przestrzeń projektową.

Gdy podejmiesz decyzję, udokumentuj ją. Architecture Decision Records (ADR) utrwalają kontekst, decyzję i konsekwencje, dzięki czemu przyszli programiści (i przyszły ty) rozumieją, dlaczego system jest zbudowany w ten sposób.

Przechowuj ADR-y w swoim repozytorium, aby Cursor mógł się do nich odwoływać. Gdy Agent generuje nowy kod, skonsultuje ADR, aby zapewnić spójność z twoimi decyzjami architektonicznymi.

Gdy architektura jest ustalona, tryb Plan przekształca ją w konkretne kroki do wykonania.

@docs/adrs/ADR-003-multi-tenancy.md @scripts/schema.sql
Na podstawie naszego ADR dotyczącego multi-tenancy, stwórz szczegółowy plan implementacji:
Faza 1 (Tydzień 1-2): Migracja bazy danych
- Dodanie tenant_id do wszystkich 50 tabel
- Utworzenie polityk RLS dla każdej tabeli
- Uzupełnienie tenant_id dla istniejących danych
- Utworzenie migracji dodającej funkcję kontekstu tenanta
Faza 2 (Tydzień 3-4): Warstwa aplikacji
- Aktualizacja middleware auth, aby ustawiał kontekst tenanta
- Aktualizacja wszystkich zapytań bazodanowych o filtrowanie po tenancie
- Dodanie tenant_id do kontekstu każdego żądania API
Faza 3 (Tydzień 5-6): Integracja SSO
- Na podstawie naszej decyzji dotyczącej architektury auth
- Implementacja przepływów SAML i OIDC
- Obsługa JIT provisioning
Faza 4 (Tydzień 7-8): Audyt i testowanie
- Dodanie logowania audytowego dla wszystkich mutacji
- Utworzenie testów izolacji tenantów
- Testy obciążeniowe z wieloma tenantami
Dla każdej fazy wymień:
- Konkretne pliki, które muszą się zmienić
- Szacowany nakład pracy (godziny)
- Strategię testowania
- Plan wycofania, jeśli coś pójdzie nie tak

Najskuteczniejszą rzeczą, jaką możesz zrobić po podjęciu decyzji architektonicznych, jest zakodowanie ich jako reguł projektu. Zamienia to twoją architekturę z dokumentu, który ludzie czytają raz, w ograniczenie, które AI egzekwuje przy każdej interakcji.

.cursor/rules/architecture.md
# Reguły architektury systemu
## Multi-Tenancy (ADR-003)
- Każda tabela bazy danych MUSI mieć kolumnę tenant_id
- Każde zapytanie bazodanowe MUSI filtrować po tenant_id (bez globalnych zapytań oprócz admina)
- Polityki RLS wymuszają izolację; kod aplikacji zapewnia ochronę w głębi
- Nowe endpointy API MUSZĄ przyjmować kontekst tenanta z middleware auth
- Testy MUSZĄ weryfikować izolację tenantów (zapytanie jako tenant A, weryfikacja braku danych tenanta B)
## Uwierzytelnianie (ADR-004)
- Auth jest obsługiwane przez WorkOS dla SSO, niestandardowe JWT dla tokenów API
- Sesje użytkowników przechowywane w podpisanych cookies httpOnly
- Claims JWT zawierają: user_id, tenant_id, role, permissions[]
- Żadnych ról na stałe: używaj sprawdzeń opartych na uprawnieniach (user.can('orders:write'))
## Warstwa danych (ADR-002)
- Dostęp do bazy danych odbywa się przez wzorzec repozytorium (src/repositories/)
- Żadnych bezpośrednich zapytań SQL w handlerach tras ani serwisach
- Wszystkie mutacje muszą tworzyć wpis w logu audytowym
- Repliki do odczytu dla zapytań analitycznych (ANALYTICS_DATABASE_URL)
## Projektowanie API
- REST z odpowiedziami JSON
- Wszystkie endpointy wersjonowane (/v1/, /v2/)
- Paginacja oparta na kursorze (nie na offsecie)
- Odpowiedzi błędów zgodne z formatem RFC 7807 Problem Details

Mając te reguły aktywne, gdy poprosisz Agenta o utworzenie nowego endpointu API, automatycznie uwzględni filtrowanie tenantów, sprawdzanie uprawnień, logowanie audytowe i prawidłowe formatowanie błędów. Architektura nie jest tylko udokumentowana — jest egzekwowana.

Gdy twoja architektura musi obsługiwać znacznie większy ruch, użyj trybu Ask, aby zbadać strategie skalowania przed zaangażowaniem się w zmiany infrastruktury:

@src @infrastructure
Nasza aplikacja obecnie obsługuje 1000 żądań/minutę. Musimy przeskalować się do
50 000 żądań/minutę w ciągu 6 miesięcy. Obecne wąskie gardła na podstawie naszych metryk:
1. Pula połączeń PostgreSQL osiąga maksimum przy 100 połączeniach
2. Niektóre endpointy API trwają ponad 2 sekundy z powodu złożonych złączeń
3. Walidacja sesji uderza w bazę danych przy każdym żądaniu
4. Przetwarzanie obrazów blokuje wątek żądania
Dla każdego wąskiego gardła zaproponuj strategię skalowania:
- Co się zmienia w architekturze?
- Co się zmienia w infrastrukturze?
- Jaka jest ścieżka migracji z obecnego stanu do docelowego?
- Co możemy zrobić natychmiast vs co wymaga większego refaktoringu?
Rozważ: repliki do odczytu, pooling połączeń (PgBouncer), warstwy cache (Redis),
przetwarzanie asynchroniczne (kolejki zadań), CDN, skalowanie horyzontalne.

Agent podejmuje decyzje implementacyjne sprzeczne z twoją architekturą. Dzieje się tak, gdy twoje ADR-y i reguły architektoniczne nie znajdują się w kontekście AI. Zawsze utrzymuj plik .cursor/rules/architecture.md zaktualizowany i ustawiony na “Always Apply.” Gdy Agent generuje kod naruszający twoją architekturę, wskaż mu konkretną regułę: “To narusza ADR-003. Wszystkie zapytania muszą filtrować po tenant_id.”

Propozycja architektury jest zbyt abstrakcyjna. Jeśli tryb Plan daje ci niejasne rekomendacje w stylu “użyj warstwy cache”, domagaj się konkretów: “Które dane powinny być cache’owane? Jaka strategia unieważniania cache? Co się dzieje przy cache miss? Jak to współdziała z naszym RLS multi-tenancy?”

Analiza kompromisów ignoruje twoje ograniczenia. AI może zarekomendować podejście baza-danych-per-tenant, które działa w skali Google, ale jest operacyjnie niemożliwe dla twojego 3-osobowego zespołu. Zawsze jawnie określaj swoje ograniczenia: wielkość zespołu, budżet, harmonogram i dojrzałość operacyjna.

Reguły architektury stają się nieaktualne. Gdy twoja architektura ewoluuje (może migrujesz z RLS na schemat-per-tenant), natychmiast aktualizuj reguły. Nieaktualne reguły są gorsze niż brak reguł, ponieważ aktywnie kierują Agenta w stronę przestarzałych wzorców.

Plan jest zbyt ambitny. Jeśli tryb Plan generuje 6-miesięczny plan implementacji, podziel go na 2-tygodniowe fazy z wyraźnymi kamieniami milowymi. Każda faza powinna dostarczać działający system, nie tylko elementy przyszłego systemu. Zapytaj: “Przestrukturyzuj ten plan tak, aby każda faza mogła być wdrożona niezależnie i system działał poprawnie po każdej fazie.”