From 9c39ff06ba1bb9c05554a964474dba270cffcc0a Mon Sep 17 00:00:00 2001 From: Maciej Pienczyn Date: Sat, 31 Jan 2026 06:54:56 +0100 Subject: [PATCH] =?UTF-8?q?docs:=20Strategia=20Alias=20Bridge=20dla=20bezp?= =?UTF-8?q?iecznego=20wdro=C5=BCenia=20Fazy=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Odkrycie: Flask pozwala zarejestrować ten sam URL pod dwoma nazwami - url_for('login') i url_for('auth.login') mogą współistnieć - Zero zmian w szablonach podczas wdrożenia blueprintów Strategia 3 podfaz: - Faza 2a: Blueprinty + aliasy (niskie ryzyko) - Faza 2b: Stopniowa migracja szablonów - Faza 2c: Usunięcie aliasów Porównanie z Big Bang: 20 vs 125 plików do zmiany naraz Co-Authored-By: Claude Opus 4.5 --- docs/MODULAR_MONOLITH_DEPLOYMENT_STRATEGY.md | 417 +++++++++++++++++++ docs/MODULAR_MONOLITH_PLAN.md | 22 +- 2 files changed, 438 insertions(+), 1 deletion(-) create mode 100644 docs/MODULAR_MONOLITH_DEPLOYMENT_STRATEGY.md diff --git a/docs/MODULAR_MONOLITH_DEPLOYMENT_STRATEGY.md b/docs/MODULAR_MONOLITH_DEPLOYMENT_STRATEGY.md new file mode 100644 index 0000000..a645ad4 --- /dev/null +++ b/docs/MODULAR_MONOLITH_DEPLOYMENT_STRATEGY.md @@ -0,0 +1,417 @@ +# Strategia Bezpiecznego Wdrożenia Fazy 2 + +> **Data:** 2026-01-31 +> **Status:** KRYTYCZNE - wymaga starannego planowania +> **Ryzyko:** Wysokie - 125+ zmian musi być atomowych + +--- + +## Problem + +### Obecne nazwy endpointów (bez prefiksu) + +```python +# app.py +@app.route('/') +def index(): ... # url_for('index') + +@app.route('/login') +def login(): ... # url_for('login') + +@app.route('/dashboard') +def dashboard(): ... # url_for('dashboard') +``` + +### Docelowe nazwy endpointów (z prefiksem blueprintu) + +```python +# blueprints/public/routes.py +@bp.route('/') +def index(): ... # url_for('public.index') + +# blueprints/auth/routes.py +@bp.route('/login') +def login(): ... # url_for('auth.login') +``` + +### Skala zmian + +| Lokalizacja | url_for('index') | url_for('login') | url_for('dashboard') | url_for('register') | +|-------------|------------------|------------------|----------------------|---------------------| +| app.py | 18 | 10 | 43 | 0 | +| szablony | 27 | 11 | 6 | 10 | +| **RAZEM** | **45** | **21** | **49** | **10** | + +**Łącznie: ~125 miejsc do zmiany ATOMICZNIE** + +--- + +## Strategie wdrożenia + +### ❌ Opcja A: Stopniowe wdrażanie (NIEMOŻLIWE) + +Nie można wdrożyć blueprintu bez zmiany wszystkich url_for. +Każda częściowa zmiana = awaria. + +### ⚠️ Opcja B: Aliasy / Redirecty (RYZYKOWNE) + +```python +# Po rejestracji blueprintu, dodać alias w app.py: +@app.route('/_redirect_index') +def _old_index(): + return redirect(url_for('public.index')) + +# Ale url_for('index') wciąż nie zadziała! +``` + +**Problem:** Flask nie wspiera natywnie aliasów endpointów. + +### ⚠️ Opcja C: Endpoint override (CZĘŚCIOWO) + +```python +# W blueprincie - nadpisać nazwę endpointu +@bp.route('/', endpoint='index') # Bez prefiksu! +def index_view(): + ... +``` + +**Problem:** +- `url_for('index')` zadziała ✅ +- `url_for('public.index')` NIE zadziała ❌ +- `utils/decorators.py` wymaga `url_for('public.index')` ❌ + +### ✅ Opcja D: Big Bang z testami (REKOMENDOWANA) + +1. Przygotować WSZYSTKIE zmiany lokalnie +2. Uruchomić PEŁNE testy lokalne +3. Wdrożyć jednym commitem +4. Mieć gotowy rollback + +--- + +## Plan wdrożenia Fazy 2 (bezpieczny) + +### Etap 1: Przygotowanie (lokalnie) + +```bash +# 1. Stworzyć nowy branch +git checkout -b feature/phase2-auth-public + +# 2. Stworzyć blueprinty +mkdir -p blueprints/auth blueprints/public +``` + +### Etap 2: Implementacja blueprintów + +#### blueprints/auth/routes.py +- Przenieść: login, logout, register, verify-2fa, forgot-password, reset-password, verify-email, resend-verification +- Użyć: `from utils.helpers import validate_email, validate_password, sanitize_input` + +#### blueprints/public/routes.py +- Przenieść: index, company_detail, search, events, new_members, connections_map, release_notes +- Użyć: `from utils.helpers import sanitize_input` + +### Etap 3: Masowa zmiana url_for + +```bash +# Zmiana w szablonach +find templates/ -name "*.html" -exec sed -i '' \ + -e "s/url_for('index')/url_for('public.index')/g" \ + -e "s/url_for('login')/url_for('auth.login')/g" \ + -e "s/url_for('logout')/url_for('auth.logout')/g" \ + -e "s/url_for('register')/url_for('auth.register')/g" \ + -e "s/url_for('dashboard')/url_for('account.dashboard')/g" \ + {} \; + +# Zmiana w app.py +sed -i '' \ + -e "s/url_for('index')/url_for('public.index')/g" \ + -e "s/url_for('login')/url_for('auth.login')/g" \ + ... \ + app.py +``` + +### Etap 4: Testy lokalne (KRYTYCZNE!) + +```bash +# 1. Uruchomić aplikację +python3 app.py + +# 2. Testy manualne - WSZYSTKIE muszą przejść! +□ Strona główna ładuje się +□ Menu nawigacji działa +□ Link "Zaloguj" działa +□ Formularz logowania działa +□ Logowanie przekierowuje na dashboard +□ Dashboard ładuje się +□ Wylogowanie działa +□ Rejestracja działa +□ Reset hasła działa +□ Wyszukiwarka działa +□ Profil firmy działa +□ Wszystkie istniejące blueprinty działają (reports, contacts, etc.) +``` + +### Etap 5: Wdrożenie + +```bash +# 1. Commit +git add . +git commit -m "refactor(phase2): Extract auth + public blueprints + +BREAKING CHANGE: All url_for() calls updated to use blueprint prefixes: +- url_for('index') -> url_for('public.index') +- url_for('login') -> url_for('auth.login') +- url_for('register') -> url_for('auth.register') +- url_for('dashboard') -> url_for('account.dashboard') + +~125 files changed atomically." + +# 2. Push +git push origin feature/phase2-auth-public +git checkout master +git merge feature/phase2-auth-public +git push origin master && git push inpi master + +# 3. Deploy +ssh maciejpi@10.22.68.249 "cd /var/www/nordabiznes && sudo -u www-data git pull && sudo systemctl restart nordabiznes" + +# 4. Weryfikacja (natychmiast!) +curl -sI https://nordabiznes.pl/ | head -3 +curl -sI https://nordabiznes.pl/login | head -3 +curl -sI https://nordabiznes.pl/dashboard | head -3 +``` + +### Etap 6: Rollback (jeśli potrzebny) + +```bash +# Natychmiastowy rollback +git revert HEAD +git push origin master && git push inpi master +ssh maciejpi@10.22.68.249 "cd /var/www/nordabiznes && sudo -u www-data git pull && sudo systemctl restart nordabiznes" +``` + +--- + +## Checklist przed wdrożeniem + +### Przygotowanie +- [ ] Nowy branch utworzony +- [ ] Blueprinty auth i public stworzone +- [ ] Wszystkie routes przeniesione +- [ ] Wszystkie url_for zmienione w app.py +- [ ] Wszystkie url_for zmienione w szablonach +- [ ] utils/decorators.py sprawdzony + +### Testy lokalne +- [ ] Aplikacja uruchamia się bez błędów +- [ ] Strona główna działa +- [ ] Logowanie działa +- [ ] Dashboard działa +- [ ] Wylogowanie działa +- [ ] Rejestracja działa +- [ ] Menu nawigacji działa +- [ ] Istniejące blueprinty działają + +### Przed wdrożeniem +- [ ] Backup bazy danych (opcjonalnie) +- [ ] Czas wdrożenia: niska aktywność użytkowników +- [ ] Osoba monitorująca: dostępna + +### Po wdrożeniu +- [ ] Health check OK +- [ ] Strona główna OK +- [ ] Logowanie OK +- [ ] Brak błędów w logach + +--- + +## Alternatywa: Endpoint override (bezpieczniejsza?) + +Zamiast zmieniać 125 miejsc, można użyć endpoint override: + +```python +# blueprints/public/__init__.py +bp = Blueprint('public', __name__) + +# blueprints/public/routes.py +@bp.route('/', endpoint='index') # Endpoint = 'index' (bez prefiksu!) +def index(): + ... +``` + +**Zalety:** +- `url_for('index')` dalej działa ✅ +- Nie trzeba zmieniać szablonów ✅ +- Mniej ryzykowne ✅ + +**Wady:** +- `utils/decorators.py` używa `url_for('public.index')` - trzeba zmienić ❌ +- Niespójna konwencja nazewnictwa ❌ +- Trudniejsze debugowanie ❌ + +### Decyzja + +**REKOMENDACJA:** Użyć endpoint override dla pierwszego wdrożenia, potem stopniowo migrować na pełne nazwy. + +```python +# Faza 2a: Endpoint override (bezpieczne) +@bp.route('/', endpoint='index') +@bp.route('/login', endpoint='login') + +# Faza 2b: Stopniowa zmiana szablonów (później) +# url_for('index') -> url_for('public.index') +``` + +--- + +## ✅ REKOMENDOWANA STRATEGIA: Dual Endpoints (Alias Bridge) + +### Dowód koncepcji (przetestowane!) + +```python +# Flask pozwala zarejestrować ten sam URL pod dwoma nazwami: +app.register_blueprint(auth_bp) # Rejestruje /login -> auth.login + +# Dodanie aliasu dla kompatybilności wstecznej: +app.add_url_rule('/login', 'login', app.view_functions['auth.login']) + +# Wynik: +# /login -> auth.login (nowy) +# /login -> login (stary alias) + +# Oba url_for działają: +# url_for('login') = /login ✓ +# url_for('auth.login') = /login ✓ +``` + +### Plan wdrożenia (3 podfazy) + +#### Faza 2a: Blueprinty + Aliasy (BEZPIECZNE) + +```python +# blueprints/__init__.py +def register_blueprints(app): + from blueprints.auth import bp as auth_bp + from blueprints.public import bp as public_bp + + app.register_blueprint(auth_bp) + app.register_blueprint(public_bp) + + # ALIASY dla kompatybilności wstecznej + # Szablony dalej używają url_for('login'), url_for('index'), etc. + _create_endpoint_aliases(app, { + # stara_nazwa: nowa_nazwa + 'index': 'public.index', + 'login': 'auth.login', + 'logout': 'auth.logout', + 'register': 'auth.register', + 'dashboard': 'public.dashboard', # lub account.dashboard + 'search': 'public.search', + 'company_detail': 'public.company_detail', + 'company_detail_by_slug': 'public.company_detail_by_slug', + # ... wszystkie inne + }) + +def _create_endpoint_aliases(app, aliases): + """Tworzy aliasy dla starych nazw endpointów.""" + for old_name, new_name in aliases.items(): + if new_name in app.view_functions: + # Znajdź URL dla nowego endpointu + for rule in app.url_map.iter_rules(): + if rule.endpoint == new_name: + app.add_url_rule( + rule.rule, + old_name, + app.view_functions[new_name], + methods=rule.methods + ) + break +``` + +**Efekt Fazy 2a:** +- ✅ Blueprinty działają +- ✅ `url_for('login')` działa (alias) +- ✅ `url_for('auth.login')` działa (nowy) +- ✅ Szablony NIE wymagają zmian +- ✅ Zero ryzyka awarii + +#### Faza 2b: Stopniowa migracja szablonów + +```bash +# Można zmieniać po jednym szablonie +# Każda zmiana = osobny commit + +# Przykład: +sed -i '' "s/url_for('login')/url_for('auth.login')/g" templates/base.html +git commit -m "refactor: Migrate url_for in base.html" +``` + +**Efekt Fazy 2b:** +- ✅ Szablony używają nowych nazw +- ✅ Aliasy dalej działają (dla nieprzemigrowanych) +- ✅ Można robić stopniowo + +#### Faza 2c: Usunięcie aliasów (cleanup) + +```python +# Po pełnej migracji szablonów: +# Usunąć _create_endpoint_aliases() +``` + +**Efekt Fazy 2c:** +- ✅ Czysty kod +- ✅ Tylko nowe nazwy endpointów +- ✅ Pełna migracja zakończona + +--- + +## Podsumowanie strategii + +| Faza | Opis | Ryzyko | Szablony | +|------|------|--------|----------| +| **2a** | Blueprinty + aliasy | 🟢 Niskie | Bez zmian | +| **2b** | Migracja szablonów | 🟢 Niskie | Stopniowo | +| **2c** | Usunięcie aliasów | 🟢 Niskie | Po migracji | + +### Porównanie z Big Bang + +| Aspekt | Big Bang | Alias Bridge | +|--------|----------|--------------| +| Zmiany na raz | ~125 | ~20 (tylko blueprinty) | +| Ryzyko awarii | 🔴 Wysokie | 🟢 Niskie | +| Rollback | Trudny | Łatwy | +| Testowanie | Wszystko naraz | Etapami | +| Czas wdrożenia | 1 dzień | 3-5 dni (bezpiecznie) | + +--- + +## Checklist Fazy 2a + +### Przygotowanie +- [ ] Stworzyć `blueprints/auth/__init__.py` +- [ ] Stworzyć `blueprints/auth/routes.py` +- [ ] Stworzyć `blueprints/public/__init__.py` +- [ ] Stworzyć `blueprints/public/routes.py` +- [ ] Przenieść routes z app.py do blueprintów +- [ ] Dodać funkcję `_create_endpoint_aliases()` +- [ ] Zaktualizować `blueprints/__init__.py` + +### Testy lokalne +- [ ] Aplikacja uruchamia się +- [ ] `url_for('index')` działa +- [ ] `url_for('public.index')` działa +- [ ] Logowanie działa +- [ ] Strona główna działa +- [ ] Istniejące blueprinty działają + +### Wdrożenie +- [ ] Commit + push +- [ ] Deploy na produkcję +- [ ] Weryfikacja health check +- [ ] Weryfikacja logowania + +--- + +**Ostatnia aktualizacja:** 2026-01-31 +**Status:** REKOMENDOWANA STRATEGIA - Alias Bridge diff --git a/docs/MODULAR_MONOLITH_PLAN.md b/docs/MODULAR_MONOLITH_PLAN.md index c23efd8..90a631f 100644 --- a/docs/MODULAR_MONOLITH_PLAN.md +++ b/docs/MODULAR_MONOLITH_PLAN.md @@ -451,7 +451,27 @@ nordabiz/ | 10 | cleanup (usunięcie duplikatów z app.py) | 2h | Wszystkie fazy | ⏳ | | **RAZEM** | | **~39h** | | | -**UWAGA:** Faza 2 jest krytyczna - `auth` i `public` muszą być wdrożone RAZEM, bo `utils/decorators.py` wymaga obu blueprintów. +**⚠️ UWAGA:** Faza 2 jest krytyczna - `auth` i `public` muszą być wdrożone RAZEM! + +**Szczegółowa strategia:** [`docs/MODULAR_MONOLITH_DEPLOYMENT_STRATEGY.md`](MODULAR_MONOLITH_DEPLOYMENT_STRATEGY.md) + +### Strategia "Alias Bridge" (bezpieczna) + +| Podfaza | Opis | Ryzyko | +|---------|------|--------| +| **2a** | Blueprinty + aliasy dla starych nazw | 🟢 Niskie | +| **2b** | Stopniowa migracja szablonów | 🟢 Niskie | +| **2c** | Usunięcie aliasów | 🟢 Niskie | + +**Kluczowa technika:** Rejestracja tego samego URL pod dwoma nazwami +```python +# Po rejestracji blueprintu: +app.add_url_rule('/login', 'login', app.view_functions['auth.login']) + +# Efekt: +url_for('login') → /login ✓ (stary kod działa) +url_for('auth.login') → /login ✓ (nowy kod działa) +``` ---