docs: Reorganizacja dokumentacji - wydzielenie DEVELOPMENT, ROADMAP, CREDENTIALS

- CLAUDE.md uproszczony - tylko kluczowe info dla Claude
- docs/DEVELOPMENT.md - szczegóły SearchService, Chatbot, Testy AI, SEO, News
- docs/ROADMAP.md - plan rozwoju, priorytety, strategia monetyzacji 3-tier
- docs/CREDENTIALS.md - zasady zarządzania hasłami i kluczami API

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-01-22 10:26:24 +01:00
parent 9e82c00ca4
commit 587d000b9b
4 changed files with 781 additions and 944 deletions

1062
CLAUDE.md

File diff suppressed because it is too large Load Diff

168
docs/CREDENTIALS.md Normal file
View File

@ -0,0 +1,168 @@
# NordaBiz - Zarządzanie danymi uwierzytelniającymi
Ten dokument zawiera szczegółowe zasady zarządzania hasłami, kluczami API i innymi wrażliwymi danymi.
Główne instrukcje znajdują się w [CLAUDE.md](../CLAUDE.md).
---
## KRYTYCZNE: Nigdy nie umieszczaj haseł w kodzie!
**NIGDY nie umieszczaj haseł i kluczy API bezpośrednio w kodzie źródłowym!**
Jest to krytyczna podatność bezpieczeństwa (CWE-798: Use of Hard-coded Credentials). Narusza standardy bezpieczeństwa i może prowadzić do kompromitacji systemu jeśli repozytorium zostanie ujawnione.
---
## Zasady obowiązkowe
### 1. Używaj zmiennych środowiskowych
```python
# ✅ PRAWIDŁOWO:
DATABASE_URL = os.getenv('DATABASE_URL')
API_KEY = os.getenv('GOOGLE_PAGESPEED_API_KEY')
# ❌ BŁĘDNIE - NIGDY TAK NIE RÓB:
DATABASE_URL = 'postgresql://user:password123@localhost/db'
API_KEY = 'AIzaSyAbc123...'
```
### 2. Wartości domyślne jako bezpieczne placeholdery
```python
# ✅ PRAWIDŁOWO - wartość domyślna która wymusi konfigurację .env:
DATABASE_URL = os.getenv('DATABASE_URL', 'postgresql://user:CHANGE_ME@localhost/nordabiz')
# ❌ BŁĘDNIE - wartość produkcyjna jako fallback:
DATABASE_URL = os.getenv('DATABASE_URL', 'postgresql://user:RealPassword@10.22.68.249/nordabiz')
```
### 3. Przechowuj credentials w plikach .env
| Środowisko | Lokalizacja |
|------------|-------------|
| Produkcja | `/var/www/nordabiznes/.env` |
| Development | `.env` w katalogu projektu |
| Wzorzec | `.env.example` (bez prawdziwych wartości!) |
---
## Wymagane zmienne środowiskowe
| Zmienna | Cel | Przykład |
|---------|-----|----------|
| `DATABASE_URL` | Połączenie PostgreSQL dla skryptów Python | `postgresql://user:pass@127.0.0.1:5432/nordabiz` |
| `PGPASSWORD` | Hasło PostgreSQL dla skryptów shell | `export PGPASSWORD='your_password'` |
| `GOOGLE_PAGESPEED_API_KEY` | API Key Google PageSpeed | `AIzaSy...` |
| `BRAVE_SEARCH_API_KEY` | API Key Brave Search | `BSA...` |
| `GEMINI_API_KEY` | API Key Google Gemini AI | `AIzaSy...` |
---
## Skrypty shell - sprawdzanie zmiennych
```bash
# ✅ PRAWIDŁOWO:
if [ -z "$PGPASSWORD" ]; then
echo "ERROR: PGPASSWORD not set"
exit 1
fi
psql -h localhost -U nordabiz_app -d nordabiz
# ❌ BŁĘDNIE:
PGPASSWORD='hardcoded_password' psql -h localhost -U nordabiz_app -d nordabiz
```
---
## NIGDY nie commituj plików z credentials
- `.env` jest w `.gitignore`
- Sprawdzaj przed commitem: `git diff` i `git status`
- W razie wątpliwości: `git log -p | grep -i password`
---
## Co zrobić jeśli przypadkowo scommitujesz hasło
⚠️ **NATYCHMIAST zmień hasło w bazie/API**
Powód: Nie wystarczy usunąć z najnowszego commita - hasło pozostaje w historii Git.
### Opcje naprawy:
1. **Zmiana hasła** (ZALECANE)
- Natychmiast zmień hasło we wszystkich systemach
- Traktuj stare hasło jako skompromitowane
- Najprostsze i najbezpieczniejsze rozwiązanie
2. **Przepisanie historii Git** (SKOMPLIKOWANE)
- `git filter-branch` lub `BFG Repo-Cleaner`
- Wymaga force push do wszystkich remotów
- Może powodować problemy dla innych deweloperów
---
## Wyjątki - kiedy dozwolone jest hasło w kodzie
| Dozwolone | Niedozwolone |
|-----------|--------------|
| ✅ Pliki dokumentacji (CLAUDE.md, README) | ⛔ Pliki Python (.py) |
| ✅ `.env.example` z placeholderami | ⛔ Skrypty shell (.sh) |
| | ⛔ Pliki JavaScript (.js) |
---
## Weryfikacja przed wdrożeniem
```bash
# Sprawdź czy nie ma hardcoded credentials w kodzie:
grep -r "PGPASSWORD=" --include="*.sh" .
grep -r "postgresql://.*:.*@" --include="*.py" . | grep -v "CHANGE_ME" | grep -v ".example" | grep -v "PASSWORD"
# Oczekiwany wynik: brak znalezisk (lub tylko w dokumentacji/placeholderach)
```
---
## Bezpieczne przechowywanie
### Lokalizacje plików .env
```
/var/www/nordabiznes/.env # Produkcja (PROD)
./nordabiz/.env # Development (DEV)
```
### Uprawnienia plików
```bash
# Tylko właściciel może czytać plik .env
chmod 600 /var/www/nordabiznes/.env
chown www-data:www-data /var/www/nordabiznes/.env
```
---
## Konfiguracja IDE
### VS Code - wykluczenie .env z wyszukiwania
```json
// .vscode/settings.json
{
"search.exclude": {
"**/.env": true
}
}
```
### Git - ignorowanie .env
```gitignore
# .gitignore
.env
.env.local
.env.*.local
*.env
```

272
docs/DEVELOPMENT.md Normal file
View File

@ -0,0 +1,272 @@
# NordaBiz - Dokumentacja deweloperska
Ten dokument zawiera szczegółowe informacje techniczne dla deweloperów.
Główne instrukcje znajdują się w [CLAUDE.md](../CLAUDE.md).
---
## SearchService (search_service.py)
Unified search dla chatbota AI i wyszukiwarki `/search`.
### Funkcje
- **NIP/REGON lookup** - bezpośrednie wyszukiwanie po identyfikatorach
- **Synonym expansion** - rozszerzenie słów kluczowych (np. "strony" → www, web, portal)
- **PostgreSQL FTS** - full-text search z tsvector (DEV i PROD)
- **SQLite fallback** - keyword scoring (tylko jako fallback, nieużywane)
- **Fuzzy matching** - pg_trgm dla literówek (gdy dostępne)
### Scoring
| Pole | Punkty |
|------|--------|
| Nazwa firmy | +10 |
| Opis | +5 |
| Usługi | +8 |
| Kompetencje | +7 |
| Miasto | +3 |
### Użycie
```python
from search_service import search_companies
results = search_companies(db, "strony www", limit=10)
# Zwraca List[SearchResult] z company, score, match_type
```
### UWAGA (PostgreSQL)
- Gdy FTS się nie powiedzie, wykonywany jest `db.rollback()` przed fallbackiem
- Bez tego następuje błąd `InFailedSqlTransaction`
---
## Chatbot AI (nordabiz_chat.py)
### Konfiguracja
- **Limit firm do AI:** 8 (zmienne w `_build_conversation_context`, linia ~312)
- **Historia wiadomości:** 10 ostatnich
- **Search:** używa `search_companies()` z SearchService
---
## Testy jakości AI
### Uruchomienie
```bash
python run_ai_quality_tests.py -v # Verbose output
python run_ai_quality_tests.py -v -s # Verbose + save report
python run_ai_quality_tests.py -q # Quick (tylko high-priority)
```
### Przypadki testowe (`tests/ai_quality_test_cases.json`)
- 15 przypadków w 8 kategoriach
- Próg zaliczenia: 70%
- Kategorie: IT/Web, Services/Legal, Services/Accounting, Production/Metal, Construction, HVAC, Energy/Renewable, IT/Security
---
## News Monitoring
### Brave Search API Integration
**Konfiguracja:**
- API Key w `.env`: `BRAVE_SEARCH_API_KEY`
- Endpoint: `https://api.search.brave.com/res/v1/news/search`
- Limit: 2000 req/miesiąc (free tier)
**Parametry wyszukiwania:**
```python
params = {
"q": f'"{company_name}" OR "{nip}"',
"count": 10,
"freshness": "pw", # past week
"country": "pl",
"search_lang": "pl"
}
```
### AI Filtering (Gemini)
Filtracja wyników przez Google Gemini:
- Ocena relevance_score (0.0-1.0)
- Kategoryzacja news_type
- Wykrywanie duplikatów/spamu
- Automatyczne odrzucanie wyników < 0.3 relevance
**Prompt systemu:**
```
Oceń czy artykuł dotyczy działalności firmy {company_name}.
Zwróć JSON: {"relevance": 0.0-1.0, "type": "news_mention|press_release|award", "reason": "..."}
```
### Panel admina /admin/news
**URL:** `/admin/news`
**Wymaga:** Zalogowany użytkownik z `is_admin=True`
**Funkcje:**
- Lista newsów pending do moderacji
- Filtrowanie po firmie, statusie, dacie
- Zatwierdzanie/odrzucanie z powodem
- Podgląd oryginalnego artykułu
- Bulk actions (zatwierdź wszystkie z relevance > 0.8)
### Sekcja Aktualności na profilu firmy
**Lokalizacja:** `templates/company_detail.html`
**Warunek:** Tylko newsy ze statusem `approved`
**Sortowanie:** Po `published_at` DESC
**Limit:** 5 ostatnich newsów
**Struktura wyświetlania:**
```
AKTUALNOŚCI
├── [data] Tytuł artykułu (źródło)
│ Krótki opis...
│ [Czytaj więcej →]
└── [data] Kolejny artykuł...
```
### System powiadomień
**Endpoint:** `/api/notifications`
**Zwraca:** JSON z listą powiadomień użytkownika
**Typy powiadomień:**
- `new_news` - nowy news o obserwowanej firmie (dla zalogowanych)
- `news_approved` - news firmy użytkownika został zatwierdzony
- `news_rejected` - news firmy użytkownika został odrzucony
**Struktura odpowiedzi:**
```json
{
"notifications": [
{
"id": 1,
"type": "new_news",
"message": "Nowa wzmianka o PIXLAB",
"url": "/company/pixlab-sp-z-o-o#news",
"created_at": "2025-12-29T10:30:00",
"read": false
}
],
"unread_count": 3
}
```
---
## Audyt SEO (Panel /admin/seo)
### Opis
System audytu SEO stron internetowych firm członkowskich Norda Biznes.
Wykorzystuje Google PageSpeed Insights API do analizy wydajności i jakości stron.
**URL panelu:** `/admin/seo`
**Wymaga:** Zalogowany użytkownik z `is_admin=True`
### Konfiguracja API
**Google PageSpeed Insights API:**
- API Key w `.env`: `GOOGLE_PAGESPEED_API_KEY`
- Projekt Google Cloud: NORDABIZNES (`gen-lang-client-0540794446`)
- Limit: 25,000 zapytań/dzień (free tier)
- Endpoint: `https://www.googleapis.com/pagespeedonline/v5/runPagespeed`
**Klucz API:**
- **Nazwa w Google Cloud:** `Page SPEED SEO Audit v2`
- **Wartość:** Przechowywany w `.env` (GOOGLE_PAGESPEED_API_KEY)
### Metryki audytu
| Metryka | Źródło | Skala |
|---------|--------|-------|
| WYNIK SEO | PageSpeed Insights | 0-100 |
| PERFORMANCE | PageSpeed Insights | 0-100 |
| DOSTĘPNOŚĆ | PageSpeed Insights | 0-100 |
| BEST PRACTICES | PageSpeed Insights | 0-100 |
**Interpretacja wyników:**
- 90-100 (zielony) - Doskonały
- 50-89 (żółty) - Wymaga poprawy
- 0-49 (czerwony) - Słaby
### Skrypty SEO
```bash
# Audyt pojedynczej firmy
cd /var/www/nordabiznes/scripts
python seo_audit.py --company-id 26
# Audyt wsadowy (batch)
python seo_audit.py --batch 1-10
# Audyt wszystkich firm
python seo_audit.py --all
# Tryb testowy (bez zapisu)
python seo_audit.py --company-id 26 --dry-run
```
### WAŻNE - Połączenie z bazą danych
Skrypty w `scripts/` muszą używać **localhost (127.0.0.1)** do połączenia z PostgreSQL:
```python
# PRAWIDŁOWO (hasło z .env):
DATABASE_URL = 'postgresql://nordabiz_app:<PASSWORD_FROM_ENV>@127.0.0.1:5432/nordabiz'
# BŁĘDNIE (PostgreSQL nie akceptuje zewnętrznych połączeń):
DATABASE_URL = 'postgresql://nordabiz_app:<PASSWORD>@10.22.68.249:5432/nordabiz'
```
**Pliki z konfiguracją bazy:**
- `scripts/seo_audit.py` (linia ~79)
- `scripts/seo_report_generator.py` (linia ~47)
- `scripts/social_media_audit.py` (linia ~53)
### UI - Stylizowane modale
Panel SEO używa niestandardowych modali (zamiast natywnych `confirm()`/`alert()`):
- Modal potwierdzenia audytu z ikoną ostrzeżenia
- Modal informacyjny o błędach
- Animacje CSS (fade in/out)
**Lokalizacja kodu:** `templates/admin_seo_dashboard.html`
---
## Social Media
### Skrypty aktualizacji
```bash
# Aktualizacja Social Media z pliku JSON
cd /var/www/nordabiznes
sudo -u www-data /var/www/nordabiznes/venv/bin/python3 update_social_media.py --dry-run # Test
sudo -u www-data /var/www/nordabiznes/venv/bin/python3 update_social_media.py # Produkcja
```
**Pliki:**
- `social_media_found.json` - wyniki wyszukiwania (źródło danych)
- `update_social_media.py` - skrypt aktualizujący bazę
**Platformy:** facebook, instagram, youtube, linkedin, tiktok, twitter
---
## Skrypty danych
### Import (wykonywać kolejno)
```bash
python import_norda_companies.py # Batch 1 (56 firm)
python import_norda_batch2.py # Batch 2
python import_norda_batch3.py # Batch 3
python import_norda_batch4.py # Batch 4 (9 firm)
python import_norda_batch5.py # Batch 5 (8 firm)
```
### Weryfikacja
```bash
python verify_all_companies_data.py # Raport jakości danych
python fix_krs_verification.py # Weryfikacja KRS
```

223
docs/ROADMAP.md Normal file
View File

@ -0,0 +1,223 @@
# NordaBiz - Plan rozwoju i monetyzacja
Ten dokument zawiera plany rozwoju projektu i strategię monetyzacji.
Główne instrukcje znajdują się w [CLAUDE.md](../CLAUDE.md).
---
## Status wdrożonych funkcjonalności
| Funkcjonalność | Status | Data |
|----------------|--------|------|
| Social Media Audit | ✅ Wdrożone | 2026-01-09 |
| News Monitoring | ✅ Wdrożone | 2025-12-29 |
| Katalog firm | ✅ Wdrożone | 2025-11-23 |
| Chat AI (NordaGPT) | ✅ Wdrożone | 2025-11-23 |
---
## Priorytet 1: Social Media Integration (Posts/Events)
**Status:** Planowane
**Cel:** Pobieranie postów i wydarzeń z Social Media firm
### Źródła danych
- Facebook Pages firm członkowskich (posty, wydarzenia)
- LinkedIn Company Pages
- Google My Business (recenzje, posty)
### Wymagania techniczne
- Facebook Graph API (wymaga App Review dla pages_read_engagement)
- LinkedIn Marketing API (wymaga partnera lub OAuth)
- Google Business Profile API
### Typy zdarzeń do importu
- `social_post` - posty z social media
- `social_event` - wydarzenia z Facebooka
- `review` - nowe recenzje Google
---
## Priorytet 2: News Monitoring (Google/Brave API)
**Status:** ✅ Wdrożone (2025-12-29)
### Źródła danych
- Wzmianki o firmach w mediach lokalnych/branżowych
- Artykuły prasowe
- Komunikaty branżowe
### Typy zdarzeń
- `news_mention` - wzmianka w mediach
- `press_release` - komunikat prasowy
- `award` - nagroda/wyróżnienie
---
## Priorytet 3: Zarząd i Wspólnicy (rejestr.io)
**Status:** Planowane
**Cel:** Wyświetlanie osób powiązanych z firmą bezpośrednio na stronie profilu
### Dane do pobrania z rejestr.io
- Zarząd (Prezes, Wiceprezes, Członkowie Zarządu)
- Prokurenci
- Wspólnicy z % udziałów
- Beneficjenci rzeczywiści
- Linki do profili osób (powiązania z innymi firmami)
### Wymagania techniczne
- Tabela `company_people` (company_id, name, role, shares_percent, person_url)
- Scraper Playwright (już mamy bazę w `analyze_connections.py`)
- Sekcja w `company_detail.html` po "Informacje prawne i biznesowe"
### Przykład wyświetlania
```
👥 ZARZĄD I WSPÓLNICY
┌─────────────────────────────────────────┐
│ 👔 Jan Kowalski - Prezes Zarządu │
│ 👔 Anna Nowak - Członek Zarządu │
│ 💼 Firma XYZ Sp. z o.o. - 60% udziałów │
│ 💼 Jan Kowalski - 40% udziałów │
└─────────────────────────────────────────┘
```
### Korzyści
- Widoczne powiązania między firmami Norda Biznes
- Ułatwiony networking (kto zna kogo)
- Transparentność struktury właścicielskiej
---
## Priorytet 4: System rekomendacji i zdjęć
**Status:** Planowane
**Cel:** Umożliwienie firmom członkowskim wzajemnego polecania się oraz prezentacji zdjęć
### Funkcje
- Rekomendacje między firmami (kto poleca kogo)
- Galeria zdjęć firmy (realizacje, zespół, biuro)
- Wyświetlanie na profilu firmy
---
## Priorytet 5: Status członkostwa i płatności
**Status:** Planowane
**Cel:** Śledzenie statusu członkostwa i składek miesięcznych
### Funkcje
- Status członka (aktywny, zawieszony, były członek)
- Informacja o opłaconych składkach
- Historia płatności
- Przypomnienia o zaległościach (dla admina)
---
## Notatki implementacyjne
- Scraper powinien deduplikować wydarzenia (hash tytułu + daty)
- Moderacja: nowe wydarzenia jako "pending" do zatwierdzenia przez admina
- Rate limiting: max 100 requestów/dzień do zewnętrznych API
---
## Forma prawna Norda Biznes
### Stan obecny
- **Forma:** OPP (Organizacja Pożytku Publicznego)
- **Typ:** Stowarzyszenie non-profit
### Planowana transformacja
- **Docelowa forma:** Działalność gospodarcza (przy Izbie)
- **Cel:** Możliwość pozyskiwania dofinansowań (granty, projekty UE)
- **Korzyści:**
- Dostęp do funduszy na rozwój platformy
- Możliwość świadczenia płatnych usług
- Elastyczność finansowa
---
## Strategia monetyzacji
### Model 3-tier Pricing (Kotwiczenie ceny)
**Strategia:** Trzy poziomy cenowe z zastosowaniem psychologii kotwiczenia ceny (Price Anchoring).
Najwyższy poziom służy jako **kotwica** - sprawia że środkowy wydaje się atrakcyjny i jest docelowy.
| Poziom | Nazwa | Cena/mies. | Cel strategiczny |
|--------|-------|------------|------------------|
| **1** | Basic | ~49 zł | Entry point, ograniczone funkcje |
| **2** | Premium | ~99 zł | **DOCELOWY** - rekomendowany, najlepsza wartość |
| **3** | Enterprise | ~199 zł | **KOTWICA** - premium, pełny dostęp |
**Wyjątek:** Członkowie Izby NORDA płacący składki (~200 zł/mies.) mają specjalny status - dostęp Premium za symboliczne 1 zł.
### Psychologia 3-tier Pricing
- Ludzie naturalnie wybierają środkową opcję (efekt kompromisu)
- Wysoka cena kotwicy sprawia że środkowa wydaje się "okazją"
- Niska cena Basic sprawia że użytkownik czuje "upgrade jest wart dopłaty"
- Firmy stosujące 3-tier widzą ~30% wzrost przychodów
- Slack: dodanie Enterprise tier zwiększyło konwersję na Professional o 28%
### Matryca dostępu do funkcji
| Funkcja | Basic | Premium | Enterprise |
|---------|:-----:|:-------:|:----------:|
| Katalog firm | ✅ | ✅ | ✅ |
| Profil firmy | ✅ | ✅ | ✅ |
| Forum | ❌ | ✅ | ✅ |
| Kalendarz wydarzeń | ❌ | ✅ | ✅ |
| Chat AI (NordaGPT) | ❌ | ✅ | ✅ |
| **Raporty podstawowe** | ❌ | ✅ | ✅ |
| **Raporty zaawansowane** | ❌ | ❌ | ✅ |
| Eksport danych (CSV/PDF) | ❌ | ❌ | ✅ |
| API dostęp | ❌ | ❌ | ✅ |
| Priorytetowe wsparcie | ❌ | ❌ | ✅ |
### Implementacja techniczna (przyszłość)
```python
# Model User - nowe pola
class User(Base):
# ...
subscription_tier = Column(String(20), default='basic') # basic, premium, enterprise
subscription_expires_at = Column(DateTime)
is_norda_member = Column(Boolean, default=False) # Członek Izby = specjalny status
# Dekorator kontroli dostępu
def requires_tier(min_tier):
def decorator(f):
@wraps(f)
def wrapped(*args, **kwargs):
tiers = ['basic', 'premium', 'enterprise']
user_tier_idx = tiers.index(current_user.subscription_tier)
required_idx = tiers.index(min_tier)
if user_tier_idx < required_idx:
flash(f'Ta funkcja wymaga konta {min_tier.title()}.', 'warning')
return redirect(url_for('pricing'))
return f(*args, **kwargs)
return wrapped
return decorator
# Użycie
@app.route('/raporty/zaawansowane')
@login_required
@requires_tier('enterprise')
def advanced_reports():
...
```
### Raporty - podział według poziomu
**Raporty podstawowe (Premium+):**
- Staż członkostwa w Izbie NORDA
- Pokrycie Social Media
- Struktura branżowa
**Raporty zaawansowane (Enterprise only):**
- Ranking SEO
- Mapa lokalizacji
- Sieć rekomendacji
- Aktywność w wydarzeniach