# Flask Application Component Diagram (C4 Level 3)

**Document Version:** 1.0
**Last Updated:** 2026-01-10
**Status:** Production LIVE
**Diagram Type:** C4 Model - Level 3 (Components)

---

## Overview

This diagram shows the **internal component structure** of the Flask web application. It illustrates:

- **What components exist** within the Flask application (routes, services, models)
- **How components interact** with each other
- **Responsibilities** of each component layer
- **Code organization** and module structure

**Abstraction Level:** Component (C4 Level 3)
**Audience:** Developers, Technical Leads
**Purpose:** Understanding internal application architecture for development and maintenance

**Application Size:** ~13,144 lines of Python code
**Total Routes:** 90+ HTTP endpoints
**Database Models:** 36 SQLAlchemy models
**Service Components:** 7 service layer modules

---

## Flask Component Architecture Diagram

```mermaid
graph TB
    %% External input
    HTTP["📨 HTTP Requests<br/>(from NPM Proxy)"]

    %% Flask App boundary
    subgraph "Flask Application (app.py - 13,144 lines)"

        %% Request handling layer
        subgraph "Request Handling Layer"
            Router["🔀 Flask Router<br/>(URL routing)"]
            Auth["🔐 Authentication<br/>(Flask-Login)<br/>User loader, session mgmt"]
            CSRF["🛡️ CSRF Protection<br/>(Flask-WTF)<br/>Token validation"]
            RateLimit["⏱️ Rate Limiter<br/>(Flask-Limiter)<br/>200/day, 50/hour"]
        end

        %% Route categories
        subgraph "Route Controllers (90+ endpoints)"
            PublicRoutes["🌐 Public Routes (8)<br/>/, /search, /company/slug<br/>/aktualnosci, /health"]
            AuthRoutes["🔑 Auth Routes (7)<br/>/register, /login, /logout<br/>/verify-email, /reset-password"]
            UserRoutes["👤 User Routes (21)<br/>/dashboard, /chat, /forum<br/>/wiadomosci, /kalendarz, /tablica"]
            AdminRoutes["👨‍💼 Admin Routes (28)<br/>/admin/seo, /admin/forum<br/>/admin/users, /admin/fees"]
            APIRoutes["🔌 API Routes (26)<br/>/api/chat, /api/seo, /api/companies<br/>/api/notifications, /api/recommendations"]
            AuditRoutes["📊 Audit Routes (4)<br/>/audit/seo, /audit/social<br/>/audit/gbp, /audit/it"]
        end

        %% Service layer
        subgraph "Service Layer (7 modules)"
            SearchService["🔍 SearchService<br/>search_service.py<br/>~400 lines<br/><br/>• Company search<br/>• NIP/REGON lookup<br/>• PostgreSQL FTS<br/>• Synonym expansion<br/>• Fuzzy matching<br/>• Result scoring"]

            ChatService["💬 ChatService<br/>nordabiz_chat.py<br/>~800 lines<br/><br/>• AI conversation<br/>• Context building<br/>• Session management<br/>• Token tracking<br/>• Message history"]

            GeminiService["🤖 GeminiService<br/>gemini_service.py<br/>~500 lines<br/><br/>• AI text generation<br/>• Image analysis<br/>• Streaming responses<br/>• Cost tracking<br/>• Error handling"]

            EmailService["📧 EmailService<br/>email_service.py<br/>~200 lines<br/><br/>• MS Graph OAuth<br/>• Email sending<br/>• Template rendering<br/>• Error handling"]

            KRSService["🏛️ KRSService<br/>krs_api_service.py<br/>~300 lines<br/><br/>• Company verification<br/>• Registry data fetch<br/>• Data validation<br/>• Caching"]

            GBPService["📊 GBPService<br/>gbp_audit_service.py<br/>~600 lines<br/><br/>• Places API search<br/>• Profile analysis<br/>• AI recommendations<br/>• Audit reporting"]

            ITService["🖥️ ITService<br/>it_audit_service.py<br/>~500 lines<br/><br/>• IT maturity assess<br/>• Question scoring<br/>• Report generation<br/>• Recommendations"]
        end

        %% Database layer
        subgraph "Database Layer (database.py - ~1,500 lines)"
            ORM["🗄️ SQLAlchemy ORM<br/>Session management<br/>Query building"]

            subgraph "Domain Models (36 total)"
                CoreModels["📂 Core Domain (5)<br/>Company, User, Category<br/>CompanyOwner, SearchHistory"]

                ContentModels["📝 Content Domain (6)<br/>CompanyNews, NewsVerification<br/>ForumTopic, ForumReply, ClassifiedAd<br/>CompanyPhoto"]

                SocialModels["👥 Social Domain (5)<br/>CompanySocialMedia<br/>SocialMediaAudit<br/>SocialMediaProfile<br/>Recommendation, Like"]

                AuditModels["📊 Audit Domain (4)<br/>SEOMetrics, GBPAudit<br/>ITInfrastructureAudit<br/>DigitalMaturityScore"]

                ChatModels["💬 Chat Domain (3)<br/>ChatSession, ChatMessage<br/>GeminiUsage"]

                CommunityModels["🤝 Community Domain (5)<br/>Event, EventAttendee<br/>MembershipFee, Message<br/>Notification"]

                SystemModels["⚙️ System Domain (8)<br/>EmailVerification, PasswordReset<br/>APIQuota, APILog, DataQualityCheck<br/>ActivityLog, AuditLog, SystemSetting"]
            end
        end

        %% Template rendering
        Templates["📄 Template Engine<br/>(Jinja2)<br/>HTML rendering<br/>Template inheritance"]

        %% Static files
        Static["🎨 Static Assets<br/>CSS, JavaScript, Images"]
    end

    %% External dependencies
    Database[("💾 PostgreSQL<br/>Database<br/>36 tables")]
    GeminiAPI["🤖 Gemini API<br/>(external)"]
    BraveAPI["🔍 Brave API<br/>(external)"]
    PageSpeedAPI["📊 PageSpeed API<br/>(external)"]
    PlacesAPI["📍 Places API<br/>(external)"]
    KRSAPI["🏛️ KRS API<br/>(external)"]
    MSGraphAPI["📧 MS Graph API<br/>(external)"]

    %% Request flow
    HTTP --> Router
    Router --> Auth
    Router --> CSRF
    Router --> RateLimit

    Auth --> PublicRoutes
    Auth --> AuthRoutes
    Auth --> UserRoutes
    Auth --> AdminRoutes
    Auth --> APIRoutes
    Auth --> AuditRoutes

    %% Route to service connections
    PublicRoutes --> SearchService
    PublicRoutes --> Templates

    UserRoutes --> ChatService
    UserRoutes --> SearchService
    UserRoutes --> Templates

    AdminRoutes --> GBPService
    AdminRoutes --> ITService
    AdminRoutes --> Templates

    APIRoutes --> ChatService
    APIRoutes --> SearchService
    APIRoutes --> GBPService

    AuditRoutes --> Templates

    %% Service to service connections
    ChatService --> SearchService
    ChatService --> GeminiService
    GBPService --> GeminiService

    %% Service to external API connections
    GeminiService --> GeminiAPI
    ChatService --> GeminiAPI
    SearchService --> Database
    EmailService --> MSGraphAPI
    KRSService --> KRSAPI
    GBPService --> PlacesAPI

    %% Database access
    PublicRoutes --> ORM
    UserRoutes --> ORM
    AdminRoutes --> ORM
    APIRoutes --> ORM

    ORM --> CoreModels
    ORM --> ContentModels
    ORM --> SocialModels
    ORM --> AuditModels
    ORM --> ChatModels
    ORM --> CommunityModels
    ORM --> SystemModels

    CoreModels --> Database
    ContentModels --> Database
    SocialModels --> Database
    AuditModels --> Database
    ChatModels --> Database
    CommunityModels --> Database
    SystemModels --> Database

    %% Template rendering
    Templates --> Static

    %% Styling
    classDef routeStyle fill:#1168bd,stroke:#0b4884,color:#ffffff,stroke-width:2px
    classDef serviceStyle fill:#85bbf0,stroke:#5d92c7,color:#000000,stroke-width:2px
    classDef modelStyle fill:#50c878,stroke:#3da35f,color:#000000,stroke-width:2px
    classDef infraStyle fill:#ff9f1c,stroke:#cc7f16,color:#000000,stroke-width:2px
    classDef externalStyle fill:#999999,stroke:#666666,color:#ffffff,stroke-width:2px
    classDef databaseStyle fill:#438dd5,stroke:#2e6295,color:#ffffff,stroke-width:3px

    class PublicRoutes,AuthRoutes,UserRoutes,AdminRoutes,APIRoutes,AuditRoutes routeStyle
    class SearchService,ChatService,GeminiService,EmailService,KRSService,GBPService,ITService serviceStyle
    class CoreModels,ContentModels,SocialModels,AuditModels,ChatModels,CommunityModels,SystemModels modelStyle
    class Router,Auth,CSRF,RateLimit,ORM,Templates,Static infraStyle
    class GeminiAPI,BraveAPI,PageSpeedAPI,PlacesAPI,KRSAPI,MSGraphAPI externalStyle
    class Database databaseStyle
```

---

## Component Descriptions

### 1. Request Handling Layer

#### 🔀 Flask Router
**Location:** `app.py` (Flask core)
**Responsibility:** URL pattern matching and request routing
**Technology:** Flask routing decorators (`@app.route()`)

**Key Features:**
- 90+ registered routes across 6 categories
- RESTful API endpoints (`/api/*`)
- Dynamic URL parameters (`<slug>`, `<id>`)
- Multiple HTTP methods (GET, POST, PUT, DELETE)

**Example Routes:**
```python
@app.route('/')                          # Homepage
@app.route('/company/<slug>')            # Company profile
@app.route('/api/chat/<id>/message')     # API endpoint
@app.route('/admin/seo')                 # Admin panel
```

#### 🔐 Authentication (Flask-Login)
**Location:** `app.py` (lines ~200-400)
**Responsibility:** User authentication and session management
**Technology:** Flask-Login extension

**Key Features:**
- Session-based authentication (cookies)
- User loader callback (`@login_manager.user_loader`)
- Login required decorator (`@login_required`)
- Remember me functionality
- Session persistence

**Authentication Levels:**
- **Public:** Anonymous access allowed
- **User:** Requires login (`current_user.is_authenticated`)
- **Admin:** Requires admin flag (`current_user.is_admin`)

**Session Storage:** Server-side sessions in PostgreSQL (or cookies for simple data)

#### 🛡️ CSRF Protection (Flask-WTF)
**Location:** `app.py` (Flask-WTF integration)
**Responsibility:** Cross-Site Request Forgery protection
**Technology:** Flask-WTF CSRFProtect

**Key Features:**
- Automatic CSRF token generation
- Form validation with CSRF tokens
- AJAX request protection (X-CSRFToken header)
- Token rotation on authentication changes

**Protected Routes:** All POST, PUT, DELETE requests
**Exempt Routes:** `/health`, `/api/webhooks` (if needed)

#### ⏱️ Rate Limiter (Flask-Limiter)
**Location:** `app.py` (Flask-Limiter integration)
**Responsibility:** API rate limiting and abuse prevention
**Technology:** Flask-Limiter

**Rate Limits:**
- **Global Default:** 200 requests/day, 50 requests/hour
- **Chat API:** 100 requests/day (AI cost control)
- **Search API:** 200 requests/hour
- **Admin API:** Unlimited (trusted users)

**Storage:** Redis (production) or in-memory (development)
**Key Function:** `get_remote_address()` for IP-based limiting

---

### 2. Route Controllers (90+ endpoints)

#### 🌐 Public Routes (8 endpoints)
**Authentication:** None required
**Purpose:** Publicly accessible pages

| Route | Method | Description | Template |
|-------|--------|-------------|----------|
| `/` | GET | Homepage - company directory | `index.html` |
| `/search` | GET | Search companies | `search_results.html` |
| `/company/<slug>` | GET | Company profile page | `company_detail.html` |
| `/aktualnosci` | GET | News feed | `news.html` |
| `/health` | GET | Health check (JSON) | - |
| `/release-notes` | GET | Release notes | `release_notes.html` |
| `/api/companies` | GET | JSON export of companies | - |
| `/api/verify-nip` | GET | NIP verification API | - |

**Key Features:**
- No authentication required
- Cacheable responses
- SEO-optimized (meta tags, structured data)
- Rate limited to prevent scraping

#### 🔑 Auth Routes (7 endpoints)
**Authentication:** Mixed (public registration, authenticated logout)
**Purpose:** User authentication lifecycle

| Route | Method | Description | Authentication |
|-------|--------|-------------|----------------|
| `/register` | GET, POST | User registration | Public |
| `/login` | GET, POST | User login | Public |
| `/logout` | GET | User logout | Required |
| `/verify-email/<token>` | GET | Email verification | Public |
| `/resend-verification` | POST | Resend verification email | Public |
| `/reset-password` | GET, POST | Password reset request | Public |
| `/reset-password/<token>` | GET, POST | Password reset form | Public |

**Security Features:**
- Password hashing (bcrypt)
- Email verification required
- Password strength validation
- Rate limiting on registration (5/hour)
- CSRF protection on all forms

#### 👤 User Routes (21 endpoints)
**Authentication:** Required (`@login_required`)
**Purpose:** Authenticated user features

**Categories:**
- **Dashboard:** `/dashboard` - User overview
- **Chat:** `/chat` - AI assistant interface
- **Forum:** `/forum`, `/forum/nowy`, `/forum/<id>`, `/forum/<id>/odpowiedz` (7 routes)
- **Messages:** `/wiadomosci`, `/wiadomosci/nowa`, `/wiadomosci/<id>` (5 routes)
- **Calendar:** `/kalendarz`, `/kalendarz/<id>`, `/kalendarz/<id>/rsvp` (3 routes)
- **Classifieds:** `/tablica`, `/tablica/nowe`, `/tablica/<id>` (3 routes)
- **IT Audit:** `/it-audit/form` - IT maturity self-assessment

**Key Features:**
- Personal dashboard with activity feed
- AI chat with conversation history
- Forum participation (topics, replies, moderation)
- Private messaging between members
- Event calendar with RSVP
- Classifieds board for member offers
- IT infrastructure self-audit

#### 👨‍💼 Admin Routes (28 endpoints)
**Authentication:** Required + Admin flag (`current_user.is_admin`)
**Purpose:** Administrative functions

**Categories:**

**SEO Management (1 route):**
- `/admin/seo` - SEO audit dashboard

**Social Media Management (2 routes):**
- `/admin/social-media` - Social media profiles overview
- `/admin/social-audit` - Social media audit results

**GBP Management (1 route):**
- `/admin/gbp-audit` - Google Business Profile audit dashboard

**IT Audit Management (1 route):**
- `/admin/it-audit` - IT audit results dashboard

**Forum Moderation (5 routes):**
- `/admin/forum` - Forum overview
- `/admin/forum/topic/<id>/pin` - Pin topic
- `/admin/forum/topic/<id>/delete` - Delete topic
- `/admin/forum/reply/<id>/delete` - Delete reply
- `/admin/forum/user/<id>/ban` - Ban user from forum

**Recommendations Management (3 routes):**
- `/admin/recommendations` - Pending recommendations
- `/admin/recommendations/<id>/approve` - Approve recommendation
- `/admin/recommendations/<id>/reject` - Reject recommendation

**User Management (8 routes):**
- `/admin/users` - User list
- `/admin/users/<id>/toggle-admin` - Toggle admin status
- `/admin/users/<id>/toggle-active` - Activate/deactivate user
- `/admin/users/<id>/reset-password` - Admin password reset
- `/admin/users/<id>/delete` - Delete user account
- `/admin/users/<id>/impersonate` - Login as user (debug)
- `/admin/users/export` - Export user data (CSV)
- `/admin/users/bulk-action` - Bulk operations

**Fees Management (5 routes):**
- `/admin/fees` - Membership fees overview
- `/admin/fees/generate` - Generate monthly fees
- `/admin/fees/<id>/mark-paid` - Mark fee as paid
- `/admin/fees/<id>/send-reminder` - Send payment reminder
- `/admin/fees/export` - Export fees data

**Events Management (3 routes):**
- `/admin/kalendarz` - Event management
- `/admin/kalendarz/nowy` - Create new event
- `/admin/kalendarz/<id>/edit` - Edit event

**Analytics (3 routes):**
- `/admin/chat-analytics` - AI chat usage analytics
- `/admin/debug` - Debug information panel
- `/admin/digital-maturity` - Digital maturity overview

**Security:**
- All routes check `current_user.is_admin`
- Action logging to `audit_log` table
- Confirmation dialogs for destructive actions
- CSRF protection on all POST requests

#### 🔌 API Routes (26 endpoints)
**Authentication:** Mixed (some require login, some admin-only)
**Purpose:** JSON API for AJAX requests and external integrations
**Response Format:** JSON

**Chat API (4 endpoints):**
- `POST /api/chat/start` - Start new chat session (user auth)
- `POST /api/chat/<id>/message` - Send chat message (user auth)
- `GET /api/chat/<id>/history` - Get chat history (user auth)
- `DELETE /api/chat/<id>` - Delete chat session (user auth)

**SEO API (3 endpoints):**
- `POST /api/seo/audit` - Trigger SEO audit (admin only)
- `GET /api/seo/audit/<slug>` - Get audit results (public)
- `GET /api/seo/dashboard` - Dashboard data (admin only)

**GBP API (3 endpoints):**
- `POST /api/gbp/audit` - Trigger GBP audit (admin only)
- `GET /api/gbp/audit/<slug>` - Get audit results (public)
- `GET /api/gbp/dashboard` - Dashboard data (admin only)

**Social Media API (1 endpoint):**
- `POST /api/social/audit` - Trigger social audit (admin only)

**Notifications API (4 endpoints):**
- `GET /api/notifications` - Get user notifications (user auth)
- `PUT /api/notifications/<id>/read` - Mark as read (user auth)
- `PUT /api/notifications/read-all` - Mark all as read (user auth)
- `DELETE /api/notifications/<id>` - Delete notification (user auth)

**Recommendations API (3 endpoints):**
- `GET /api/recommendations/<id>` - Get recommendation details (user auth)
- `POST /api/recommendations/create` - Create recommendation (user auth)
- `DELETE /api/recommendations/<id>` - Delete recommendation (user auth)

**Messages API (1 endpoint):**
- `GET /api/messages/unread-count` - Get unread count (user auth)

**Utility API (5 endpoints):**
- `GET /api/verify-nip` - Verify NIP number (public)
- `GET /api/check-email` - Check email availability (public)
- `GET /api/model-info` - Get AI model info (public)
- `GET /api/companies` - Export companies JSON (public)
- `GET /api/search-suggestions` - Search autocomplete (public)

**Common Patterns:**
- JSON request/response
- HTTP status codes (200, 201, 400, 401, 403, 404, 500)
- Error messages in `{"error": "message"}` format
- Success messages in `{"success": true, "data": {...}}` format
- Rate limiting applied
- CORS headers when needed

#### 📊 Audit Routes (4 endpoints)
**Authentication:** Public (read-only audit reports)
**Purpose:** Display audit results for companies

| Route | Description | Template |
|-------|-------------|----------|
| `/audit/seo/<slug>` | SEO audit report | `audit_seo.html` |
| `/audit/social/<slug>` | Social media audit report | `audit_social.html` |
| `/audit/gbp/<slug>` | Google Business Profile audit | `audit_gbp.html` |
| `/audit/it/<slug>` | IT infrastructure audit | `audit_it.html` |

**Key Features:**
- Public access (no login required)
- Read-only reports
- PDF export capability (planned)
- Share links for business owners
- Recommendations and action items
- Historical audit comparisons

---

### 3. Service Layer (7 modules)

#### 🔍 SearchService (`search_service.py` - ~400 lines)
**Purpose:** Unified company search across multiple strategies
**Primary Function:** `search_companies(db, query, limit=10)`

**Search Strategies:**
1. **NIP/REGON Direct Lookup** - Exact match on identifiers
2. **Synonym Expansion** - Expand keywords (e.g., "strony" → www, web, portal)
3. **PostgreSQL FTS** - Full-text search with tsvector (production)
4. **Fuzzy Matching** - pg_trgm for typo tolerance
5. **SQLite Fallback** - Keyword scoring (development only)

**Scoring System:**
- **Name match:** +10 points
- **Services match:** +8 points
- **Competencies match:** +7 points
- **Description match:** +5 points
- **City match:** +3 points

**Configuration:**
- **Max Results:** 10 (configurable)
- **Min Score:** 3 (filter low-quality matches)
- **Synonyms:** Defined in `SEARCH_SYNONYMS` dict

**Error Handling:**
- PostgreSQL FTS failure → rollback + fallback to SQLite
- Empty queries → return empty list
- Invalid parameters → raise ValueError

**Usage Example:**
```python
from search_service import search_companies

results = search_companies(db, "strony www", limit=10)
# Returns: List[SearchResult(company, score, match_type)]
```

#### 💬 ChatService (`nordabiz_chat.py` - ~800 lines)
**Purpose:** AI chat assistant with company context
**Primary Function:** `process_chat_message(session_id, user_message)`

**Key Responsibilities:**
1. **Session Management** - Create, load, and manage chat sessions
2. **Context Building** - Find relevant companies (max 8)
3. **History Management** - Last 10 messages per session
4. **AI Integration** - Call Gemini API with streaming
5. **Token Tracking** - Monitor usage and costs

**Context Limits:**
- **Max Companies:** 8 (prevents token overflow)
- **Max Messages:** 10 (sliding window)
- **Max Tokens:** ~30,000 input tokens
- **Streaming:** Real-time response chunks

**Database Tables:**
- `chat_sessions` - Session metadata
- `chat_messages` - Message history
- `gemini_usage` - Token usage tracking

**Cost Tracking:**
- Input tokens × $0.075 per 1M
- Output tokens × $0.30 per 1M
- Stored in `gemini_usage` table

**Example Flow:**
```python
# 1. User sends message
user_msg = "Kto robi strony www?"

# 2. Search for relevant companies
companies = search_companies(db, user_msg, limit=8)

# 3. Build context with last 10 messages
context = build_context(session, companies, history)

# 4. Call Gemini API
response = gemini_service.generate_streaming(context)

# 5. Save message and track tokens
save_message(session, user_msg, response)
track_usage(session, input_tokens, output_tokens)
```

#### 🤖 GeminiService (`gemini_service.py` - ~500 lines)
**Purpose:** Google Gemini AI API integration
**Primary Functions:**
- `generate_text(prompt, model="gemini-2.5-flash")`
- `generate_streaming(prompt, model="gemini-2.5-flash")`
- `analyze_image(image_path, prompt)`
- `moderate_content(text)`

**Supported Models:**
- **gemini-2.5-flash** - Fast, cheap ($0.075/1M tokens)
- **gemini-2.5-pro** - High quality ($1.25/1M tokens)
- **gemini-2.0-flash-exp** - Experimental (free)

**Key Features:**
1. **Text Generation** - Chat, content creation, analysis
2. **Image Analysis** - Logo recognition, screenshot analysis
3. **Streaming Responses** - Real-time output for chat
4. **Content Moderation** - Safety filters (harassment, hate, violence)
5. **Cost Tracking** - Token usage monitoring

**Configuration:**
- **API Key:** `GEMINI_API_KEY` (from .env)
- **Rate Limit:** 200 requests/day (free tier)
- **Max Tokens:** 1M input, 8K output (flash model)
- **Temperature:** 0.7 (default for chat)

**Safety Settings:**
```python
safety_settings = {
    "HARM_CATEGORY_HARASSMENT": "BLOCK_MEDIUM_AND_ABOVE",
    "HARM_CATEGORY_HATE_SPEECH": "BLOCK_MEDIUM_AND_ABOVE",
    "HARM_CATEGORY_SEXUALLY_EXPLICIT": "BLOCK_MEDIUM_AND_ABOVE",
    "HARM_CATEGORY_DANGEROUS_CONTENT": "BLOCK_MEDIUM_AND_ABOVE",
}
```

**Error Handling:**
- API errors → retry with exponential backoff
- Rate limit exceeded → graceful degradation
- Safety block → return user-friendly error message

#### 📧 EmailService (`email_service.py` - ~200 lines)
**Purpose:** Email notifications via Microsoft Graph API
**Primary Function:** `send_email(to, subject, body_html)`

**Authentication:** OAuth 2.0 (MSAL)
**Configuration:**
- **Client ID:** `MS_GRAPH_CLIENT_ID`
- **Client Secret:** `MS_GRAPH_CLIENT_SECRET`
- **Tenant ID:** `MS_GRAPH_TENANT_ID`
- **Sender:** `noreply@nordabiznes.pl`

**Email Types:**
1. **Email Verification** - Registration confirmation
2. **Password Reset** - Password recovery
3. **Payment Reminders** - Membership fees
4. **Event Notifications** - Calendar invites
5. **Forum Notifications** - New replies
6. **Admin Alerts** - System notifications

**Template Rendering:**
- Jinja2 HTML templates in `templates/emails/`
- Plain text fallback for compatibility
- Inline CSS for email client support

**Error Handling:**
- OAuth token refresh on 401
- Retry on transient failures (5xx)
- Fallback to local logging on total failure

#### 🏛️ KRSService (`krs_api_service.py` - ~300 lines)
**Purpose:** Polish company registry (KRS) verification
**Primary Function:** `fetch_company_data(krs_number)`

**API:** KRS Open API (Ministry of Justice)
**Endpoint:** `https://api-krs.ms.gov.pl/api/krs/OdpisAktualny/{krs}`
**Authentication:** Public API (no key required)

**Data Retrieved:**
- **Company Name** - Legal name
- **NIP** - Tax identification number
- **REGON** - Statistical number
- **Address** - Registered office
- **Legal Form** - Sp. z o.o., S.A., etc.
- **Share Capital** - Initial capital
- **Board Members** - Management names
- **Shareholders** - Ownership structure

**Caching:**
- Database table: `company_krs_data`
- TTL: 30 days (data rarely changes)
- Refresh on demand via admin panel

**Error Handling:**
- KRS not found → return None
- API timeout → retry 3 times
- Invalid KRS format → validation error

#### 📊 GBPService (`gbp_audit_service.py` - ~600 lines)
**Purpose:** Google Business Profile auditing
**Primary Functions:**
- `search_place(company_name, address)`
- `get_place_details(place_id)`
- `generate_recommendations(audit_data)`

**APIs Used:**
1. **Google Places API** - Place search, details, reviews
2. **Gemini AI** - Generate improvement recommendations

**Audit Metrics:**
- **Profile Completeness** - % of filled fields
- **Review Count** - Number of Google reviews
- **Average Rating** - Star rating (1-5)
- **Response Rate** - % of reviews replied to
- **Photo Count** - Number of uploaded photos
- **Verification Status** - Verified vs unverified

**Recommendations Generated by AI:**
- Complete missing profile fields
- Respond to unanswered reviews
- Upload more photos (categories: exterior, interior, products, team)
- Improve category selection
- Add special hours (holidays, events)
- Enable messaging

**Database Storage:**
- `gbp_audits` - Audit results
- `gbp_recommendations` - AI-generated recommendations

**Cost:**
- **Places API:** $0.017 per search, $0.017 per details call
- **Gemini AI:** ~$0.02 per recommendation generation

#### 🖥️ ITService (`it_audit_service.py` - ~500 lines)
**Purpose:** IT infrastructure maturity assessment
**Primary Function:** `calculate_maturity_score(responses)`

**Assessment Areas (7 domains):**
1. **Website & Online Presence** - Website quality, SEO, analytics
2. **Email & Communication** - Professional email, collaboration tools
3. **Data Security** - Backups, encryption, access control
4. **Cloud Services** - Cloud adoption, SaaS usage
5. **Business Software** - ERP, CRM, accounting tools
6. **IT Support** - Support availability, SLA
7. **Digital Skills** - Team training, digital literacy

**Scoring:**
- **Level 0:** No implementation (0 points)
- **Level 1:** Basic implementation (25 points)
- **Level 2:** Intermediate (50 points)
- **Level 3:** Advanced (75 points)
- **Level 4:** Excellent (100 points)

**Maturity Levels:**
- **0-25%:** Basic - Minimal digital presence
- **26-50%:** Developing - Some digital tools
- **51-75%:** Advanced - Good digital infrastructure
- **76-100%:** Excellent - Mature digital organization

**Report Includes:**
- Overall maturity score
- Domain-specific scores
- Recommendations for improvement
- Comparison to industry average
- Action plan with priorities

**Database Storage:**
- `it_infrastructure_audits` - Audit results
- `digital_maturity_scores` - Historical scores

---

### 4. Database Layer (36 SQLAlchemy Models)

#### 🗄️ SQLAlchemy ORM
**Location:** `database.py` (~1,500 lines)
**Purpose:** Object-Relational Mapping and database abstraction

**Key Features:**
- **Database Agnostic:** PostgreSQL (production), SQLite (development)
- **Connection Pooling:** SQLAlchemy pool management
- **Session Management:** Scoped sessions per request
- **Query Builder:** Pythonic query construction
- **Relationship Mapping:** One-to-many, many-to-many, one-to-one
- **Lazy Loading:** Relationships loaded on demand
- **Cascade Behaviors:** Delete cascade, update cascade

**Session Management:**
```python
# Request-scoped session (Flask integration)
@app.before_request
def create_session():
    db.session = db.Session()

@app.teardown_request
def close_session(exception=None):
    db.session.close()
```

**Connection String:**
```python
# Production
DATABASE_URL = "postgresql://nordabiz_app:password@127.0.0.1:5432/nordabiz"

# Development
DATABASE_URL = "postgresql://postgres:postgres@localhost:5433/nordabiz"
```

#### 📂 Domain Models (36 total)

##### Core Domain (5 models)
**Purpose:** Fundamental business entities

**1. Company**
- **Fields:** name, slug, nip, regon, krs, category, description, website, email, phone, city, address, logo_url, verified_at, data_quality_level, created_at, updated_at
- **Relationships:** social_media (1:N), news (1:N), photos (1:N), audits (1:N), recommendations (1:N), fees (1:N)
- **Indexes:** slug (unique), nip (unique), regon (unique), krs (unique), category, city
- **Full-Text Search:** tsvector on name, description, services, competencies

**2. User**
- **Fields:** email, password_hash, company_id, is_admin, is_active, email_verified_at, created_at, last_login_at
- **Relationships:** company (N:1), chat_sessions (1:N), messages_sent (1:N), messages_received (1:N), forum_topics (1:N), forum_replies (1:N)
- **Indexes:** email (unique), company_id, is_admin
- **Authentication:** bcrypt password hashing, Flask-Login integration

**3. Category**
- **Fields:** name, slug, icon, description, company_count
- **Relationships:** companies (1:N)
- **Values:** IT, Construction, Services, Production, Trade, Other

**4. CompanyOwner**
- **Fields:** company_id, name, role, shares_percent, person_url, source
- **Relationships:** company (N:1)
- **Purpose:** Track board members and shareholders (from rejestr.io)

**5. SearchHistory**
- **Fields:** user_id, query, results_count, clicked_company_id, created_at
- **Relationships:** user (N:1), clicked_company (N:1)
- **Purpose:** Search analytics and personalization

##### Content Domain (6 models)
**Purpose:** User-generated and external content

**6. CompanyNews**
- **Fields:** company_id, title, description, url, source, published_at, news_type, relevance_score, status, moderated_by, moderated_at, rejection_reason
- **Relationships:** company (N:1), moderator (N:1), verification (1:1)
- **Status:** pending, approved, rejected
- **Types:** news_mention, press_release, award

**7. NewsVerification**
- **Fields:** news_id, verified_by, verified_at, verification_notes, ai_confidence_score
- **Relationships:** news (1:1), verifier (N:1)
- **Purpose:** Track AI and manual verification of news

**8. ForumTopic**
- **Fields:** author_id, title, content, category, is_pinned, is_locked, view_count, reply_count, created_at, updated_at
- **Relationships:** author (N:1), replies (1:N)
- **Categories:** general, announcements, networking, help, offers

**9. ForumReply**
- **Fields:** topic_id, author_id, content, created_at, updated_at
- **Relationships:** topic (N:1), author (N:1)

**10. ClassifiedAd**
- **Fields:** company_id, title, description, category, price, image_url, expires_at, is_active, created_at
- **Relationships:** company (N:1)
- **Categories:** offers, requests, announcements

**11. CompanyPhoto**
- **Fields:** company_id, url, caption, category, uploaded_by, created_at
- **Relationships:** company (N:1), uploader (N:1)
- **Categories:** exterior, interior, team, products, events

##### Social Domain (5 models)
**Purpose:** Social media and community features

**12. CompanySocialMedia**
- **Fields:** company_id, platform, url, verified_at, source, is_valid, last_checked_at, check_status, page_name, followers_count
- **Relationships:** company (N:1), audits (1:N)
- **Platforms:** facebook, instagram, linkedin, youtube, tiktok, twitter

**13. SocialMediaAudit**
- **Fields:** company_id, audit_data, audit_type, audited_at
- **Relationships:** company (N:1)
- **Types:** profile_discovery, activity_check, engagement_analysis

**14. SocialMediaProfile**
- **Fields:** social_media_id, profile_data, last_fetched_at, fetch_status
- **Relationships:** social_media (1:1)
- **Purpose:** Cache profile data from APIs

**15. Recommendation**
- **Fields:** recommender_company_id, recommended_company_id, comment, rating, status, created_at, moderated_at
- **Relationships:** recommender (N:1), recommended (N:1)
- **Status:** pending, approved, rejected

**16. Like**
- **Fields:** user_id, target_type, target_id, created_at
- **Relationships:** user (N:1)
- **Target Types:** forum_topic, forum_reply, company_news, company

##### Audit Domain (4 models)
**Purpose:** SEO, GBP, and IT auditing

**17. SEOMetrics**
- **Fields:** company_id, url, seo_score, performance_score, accessibility_score, best_practices_score, pwa_score, audit_data, audited_at
- **Relationships:** company (N:1)
- **Source:** Google PageSpeed Insights API

**18. GBPAudit**
- **Fields:** company_id, place_id, audit_data, profile_completeness, review_count, average_rating, photo_count, verified_status, audited_at
- **Relationships:** company (N:1), recommendations (1:N)
- **Source:** Google Places API + Gemini AI

**19. ITInfrastructureAudit**
- **Fields:** company_id, responses, overall_score, domain_scores, recommendations, audited_at
- **Relationships:** company (N:1)
- **Purpose:** IT maturity self-assessment

**20. DigitalMaturityScore**
- **Fields:** company_id, score, level, breakdown, calculated_at
- **Relationships:** company (N:1)
- **Levels:** basic, developing, advanced, excellent

##### Chat Domain (3 models)
**Purpose:** AI chat assistant

**21. ChatSession**
- **Fields:** user_id, company_context, message_count, total_tokens, total_cost, started_at, last_message_at
- **Relationships:** user (N:1), messages (1:N), usage (1:N)

**22. ChatMessage**
- **Fields:** session_id, role, content, created_at
- **Relationships:** session (N:1)
- **Roles:** user, assistant, system

**23. GeminiUsage**
- **Fields:** session_id, model, input_tokens, output_tokens, total_tokens, cost, created_at
- **Relationships:** session (N:1)
- **Purpose:** Track AI usage and costs

##### Community Domain (5 models)
**Purpose:** Events, fees, messaging, notifications

**24. Event**
- **Fields:** title, description, location, start_time, end_time, organizer_id, max_attendees, rsvp_deadline, created_at
- **Relationships:** organizer (N:1), attendees (1:N)

**25. EventAttendee**
- **Fields:** event_id, user_id, status, rsvp_at
- **Relationships:** event (N:1), user (N:1)
- **Status:** pending, attending, declined

**26. MembershipFee**
- **Fields:** company_id, period_start, period_end, amount, status, paid_at, payment_method, notes
- **Relationships:** company (N:1)
- **Status:** pending, paid, overdue

**27. Message**
- **Fields:** sender_id, recipient_id, subject, body, is_read, read_at, created_at
- **Relationships:** sender (N:1), recipient (N:1)

**28. Notification**
- **Fields:** user_id, type, message, url, is_read, read_at, created_at
- **Relationships:** user (N:1)
- **Types:** new_news, news_approved, forum_reply, message_received, event_invite

##### System Domain (8 models)
**Purpose:** System management and logging

**29. EmailVerification**
- **Fields:** user_id, token, expires_at, verified_at, created_at
- **Relationships:** user (N:1)

**30. PasswordReset**
- **Fields:** user_id, token, expires_at, used_at, created_at
- **Relationships:** user (N:1)

**31. APIQuota**
- **Fields:** api_name, quota_limit, quota_used, period_start, period_end
- **Purpose:** Track API usage against quotas
- **APIs:** gemini, brave, pagespeed, places

**32. APILog**
- **Fields:** api_name, endpoint, request_data, response_status, response_time, created_at
- **Purpose:** API call logging and debugging

**33. DataQualityCheck**
- **Fields:** company_id, check_type, passed, issues, checked_at
- **Relationships:** company (N:1)
- **Check Types:** nip_verification, krs_verification, website_check, social_media_check

**34. ActivityLog**
- **Fields:** user_id, action, target_type, target_id, ip_address, user_agent, created_at
- **Relationships:** user (N:1)
- **Purpose:** User activity tracking

**35. AuditLog**
- **Fields:** user_id, action, target_type, target_id, changes, ip_address, created_at
- **Relationships:** user (N:1)
- **Purpose:** Admin action auditing

**36. SystemSetting**
- **Fields:** key, value, description, updated_at
- **Purpose:** Application configuration
- **Examples:** maintenance_mode, registration_enabled, chat_enabled

---

### 5. Template Rendering

#### 📄 Jinja2 Template Engine
**Location:** `templates/` directory
**Purpose:** Server-side HTML rendering

**Template Structure:**
```
templates/
├── base.html                  # Base template (layout)
├── components/                # Reusable components
│   ├── navbar.html
│   ├── footer.html
│   ├── company_card.html
│   └── pagination.html
├── index.html                 # Homepage
├── company_detail.html        # Company profile
├── search_results.html        # Search page
├── auth/                      # Authentication pages
│   ├── login.html
│   ├── register.html
│   └── reset_password.html
├── dashboard/                 # User dashboard
│   ├── dashboard.html
│   ├── chat.html
│   └── profile.html
├── admin/                     # Admin pages
│   ├── seo_dashboard.html
│   ├── forum_moderation.html
│   └── users.html
├── forum/                     # Forum pages
├── audit/                     # Audit report pages
└── emails/                    # Email templates
```

**Template Inheritance:**
```jinja2
{# base.html #}
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}Norda Biznes{% endblock %}</title>
    {% block extra_css %}{% endblock %}
</head>
<body>
    {% include 'components/navbar.html' %}

    {% block content %}{% endblock %}

    {% include 'components/footer.html' %}

    <script>{% block extra_js %}{% endblock %}</script>
</body>
</html>

{# company_detail.html #}
{% extends 'base.html' %}

{% block title %}{{ company.name }} - Norda Biznes{% endblock %}

{% block content %}
    <h1>{{ company.name }}</h1>
    <p>{{ company.description }}</p>
{% endblock %}
```

**Common Template Variables:**
- `current_user` - Logged-in user (Flask-Login)
- `request` - Flask request object
- `config` - App configuration
- `url_for()` - URL generation function
- `get_flashed_messages()` - Flash messages

**Template Filters:**
```jinja2
{{ company.created_at|datetimeformat }}     # Format datetime
{{ company.description|truncate(200) }}     # Truncate text
{{ company.name|title }}                    # Title case
{{ price|currency }}                        # Format currency
{{ url|urlize }}                            # Convert URLs to links
```

**Security:**
- **Auto-escaping:** HTML is escaped by default
- **CSRF Tokens:** Included in all forms via `{{ csrf_token() }}`
- **XSS Prevention:** Jinja2 auto-escapes all variables

---

### 6. Static Assets

#### 🎨 Static File Structure
**Location:** `static/` directory

```
static/
├── css/
│   ├── main.css              # Main stylesheet
│   ├── admin.css             # Admin panel styles
│   └── components.css        # Component styles
├── js/
│   ├── main.js               # Global JavaScript
│   ├── chat.js               # AI chat functionality
│   ├── search.js             # Search autocomplete
│   └── admin.js              # Admin panel JS
├── images/
│   ├── logo.png              # Site logo
│   ├── companies/            # Company logos
│   └── icons/                # UI icons
└── uploads/                  # User uploads (not in Git)
    ├── logos/
    └── photos/
```

**CSS Framework:** Custom CSS (no Bootstrap/Tailwind)
**JavaScript:** Vanilla JS (minimal dependencies)
**Icons:** Font Awesome or SVG icons

**Key JavaScript Modules:**
- `chat.js` - WebSocket-like streaming for AI chat
- `search.js` - Autocomplete and instant search
- `admin.js` - Admin dashboard interactions
- `forum.js` - Forum post editing and moderation

---

## Component Interaction Patterns

### Pattern 1: Public Company Search

**Flow:**
```
User → /search?q=strony www
  ↓
Router → PublicRoutes.search()
  ↓
SearchService.search_companies(db, "strony www")
  ↓ (synonym expansion)
SearchService → PostgreSQL FTS (tsvector search)
  ↓
ORM → Company model + related data
  ↓
PublicRoutes → Templates (search_results.html)
  ↓
Jinja2 → HTML response
  ↓
User Browser
```

**Key Components:**
- **Router** - `/search` route handler
- **SearchService** - Query processing and scoring
- **Database** - PostgreSQL FTS query
- **Templates** - Jinja2 rendering
- **Static** - CSS for search results

### Pattern 2: AI Chat Request

**Flow:**
```
User → /api/chat/<id>/message (POST JSON)
  ↓
Router → APIRoutes.chat_message()
  ↓
Auth → Check @login_required
  ↓
RateLimit → Check API quota (100/day)
  ↓
CSRF → Validate token
  ↓
ChatService.process_message(session_id, message)
  ↓
SearchService.search_companies(db, message, limit=8)
  ↓
ChatService → Build context (companies + history)
  ↓
GeminiService.generate_streaming(prompt)
  ↓
Gemini API → Streaming response
  ↓
ChatService → Save message to DB
  ↓
ChatService → Track token usage
  ↓
JSON response → User (streaming chunks)
```

**Key Components:**
- **Router** - `/api/chat/<id>/message` handler
- **Auth** - Flask-Login authentication
- **RateLimit** - API quota enforcement
- **ChatService** - Session and context management
- **SearchService** - Company discovery
- **GeminiService** - AI integration
- **Database** - Message and usage storage

### Pattern 3: Admin SEO Audit

**Flow:**
```
Admin → /admin/seo (GET)
  ↓
Router → AdminRoutes.seo_dashboard()
  ↓
Auth → Check current_user.is_admin
  ↓
ORM → Load SEOMetrics + Company data
  ↓
Templates → Render admin_seo_dashboard.html
  ↓
User clicks "Audit Company X"
  ↓
JavaScript → POST /api/seo/audit (AJAX)
  ↓
Router → APIRoutes.trigger_seo_audit()
  ↓
Background Script → scripts/seo_audit.py
  ↓
PageSpeed API → Audit URL
  ↓
Background Script → Parse results
  ↓
ORM → Insert/update SEOMetrics
  ↓
JSON response → Update UI
```

**Key Components:**
- **Router** - `/admin/seo` and `/api/seo/audit` handlers
- **Auth** - Admin-only access control
- **Templates** - Admin dashboard with AJAX
- **Static** - JavaScript for audit triggering
- **Background Scripts** - SEO audit execution
- **External API** - Google PageSpeed Insights
- **Database** - SEOMetrics storage

### Pattern 4: User Registration

**Flow:**
```
User → /register (GET)
  ↓
Router → AuthRoutes.register()
  ↓
Templates → Render register.html (with CSRF token)
  ↓
User submits form
  ↓
POST /register
  ↓
Router → AuthRoutes.register()
  ↓
CSRF → Validate token
  ↓
RateLimit → Check registration quota (5/hour)
  ↓
Validation → Email, password strength, company_id
  ↓
ORM → Create User (bcrypt password hash)
  ↓
EmailVerification → Create token
  ↓
EmailService.send_email(verification email)
  ↓
MSGraph API → Send email
  ↓
Redirect → /login (with flash message)
```

**Key Components:**
- **Router** - `/register` GET and POST handlers
- **CSRF** - Form protection
- **RateLimit** - Registration throttling
- **ORM** - User creation
- **EmailService** - Verification email
- **External API** - Microsoft Graph for email
- **Templates** - Registration form

---

## Data Flow Patterns

### Database Query Patterns

**1. Simple Query (ORM):**
```python
# Get company by slug
company = db.session.query(Company).filter_by(slug='pixlab-sp-z-o-o').first()
```

**2. Join Query (Relationships):**
```python
# Get company with social media
company = db.session.query(Company)\
    .options(joinedload(Company.social_media))\
    .filter_by(slug='pixlab-sp-z-o-o')\
    .first()
```

**3. Full-Text Search (PostgreSQL):**
```python
# Search companies by keyword
results = db.session.query(Company)\
    .filter(Company.search_vector.match('strony www'))\
    .order_by(desc(func.ts_rank(Company.search_vector, func.to_tsquery('strony & www'))))\
    .limit(10)\
    .all()
```

**4. Aggregation Query:**
```python
# Count companies by category
category_counts = db.session.query(
    Category.name,
    func.count(Company.id)
).join(Company).group_by(Category.name).all()
```

### Error Handling Patterns

**1. Service Layer Error Handling:**
```python
def search_companies(db, query, limit=10):
    try:
        # Try PostgreSQL FTS
        results = _search_fts(db, query, limit)
        return results
    except Exception as e:
        logger.error(f"FTS search failed: {e}")
        db.rollback()  # CRITICAL: Rollback failed transaction

        # Fallback to SQLite-style search
        return _search_fallback(db, query, limit)
```

**2. API Route Error Handling:**
```python
@app.route('/api/chat/<int:session_id>/message', methods=['POST'])
@login_required
@limiter.limit("100/day")
def chat_message(session_id):
    try:
        data = request.get_json()

        if not data or 'message' not in data:
            return jsonify({"error": "Message required"}), 400

        response = chat_service.process_message(session_id, data['message'])
        return jsonify({"success": True, "response": response}), 200

    except ValueError as e:
        return jsonify({"error": str(e)}), 400
    except Exception as e:
        logger.exception("Chat error")
        return jsonify({"error": "Internal server error"}), 500
```

**3. External API Error Handling:**
```python
def call_gemini_api(prompt):
    max_retries = 3
    retry_delay = 1  # seconds

    for attempt in range(max_retries):
        try:
            response = genai.generate_text(prompt)
            return response
        except genai.RateLimitError:
            logger.warning("Gemini rate limit exceeded")
            return {"error": "AI service temporarily unavailable"}
        except genai.APIError as e:
            if attempt < max_retries - 1:
                time.sleep(retry_delay * (2 ** attempt))  # Exponential backoff
                continue
            else:
                logger.error(f"Gemini API failed: {e}")
                raise
```

### Authentication Flow

**Login Flow:**
```
1. User submits credentials → POST /login
2. Validate CSRF token
3. Query User by email
4. Verify password (bcrypt.check_password_hash)
5. Check email_verified_at (must not be null)
6. Check is_active flag
7. Flask-Login: login_user(user, remember=True)
8. Update last_login_at timestamp
9. Set session cookie (httponly, secure, samesite)
10. Redirect to /dashboard
```

**Authorization Checks:**
```python
# Public route (no auth)
@app.route('/')
def index():
    # Anyone can access
    pass

# User route (requires login)
@app.route('/dashboard')
@login_required
def dashboard():
    # Must be authenticated
    pass

# Admin route (requires admin flag)
@app.route('/admin/users')
@login_required
def admin_users():
    if not current_user.is_admin:
        abort(403)  # Forbidden
    # Admin-only logic
    pass
```

---

## Configuration and Environment

### Environment Variables (.env)

**Required Variables:**
```bash
# Flask
SECRET_KEY=<random-secret-key>
FLASK_ENV=production  # or development

# Database
DATABASE_URL=postgresql://nordabiz_app:password@127.0.0.1:5432/nordabiz

# Google Gemini AI
GEMINI_API_KEY=<api-key>

# Brave Search API
BRAVE_SEARCH_API_KEY=<api-key>

# Google PageSpeed Insights
GOOGLE_PAGESPEED_API_KEY=<api-key>

# Google Places API
GOOGLE_PLACES_API_KEY=<api-key>

# Microsoft Graph API (Email)
MS_GRAPH_CLIENT_ID=<client-id>
MS_GRAPH_CLIENT_SECRET=<client-secret>
MS_GRAPH_TENANT_ID=<tenant-id>

# Rate Limiting
REDIS_URL=redis://localhost:6379/0  # Production only

# Session
SESSION_TYPE=filesystem  # or redis
```

**⚠️ SECURITY WARNING:**
- **NEVER** commit `.env` file to Git
- Use `.env.example` as template (without actual secrets)
- Production secrets stored on server only

### Application Configuration (app.py)

```python
# Flask configuration
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_POOL_SIZE'] = 10
app.config['SQLALCHEMY_MAX_OVERFLOW'] = 20

# Session configuration
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_PERMANENT'] = True
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)

# Security
app.config['WTF_CSRF_ENABLED'] = True
app.config['WTF_CSRF_TIME_LIMIT'] = None

# Rate limiting
app.config['RATELIMIT_STORAGE_URL'] = os.getenv('REDIS_URL', 'memory://')
app.config['RATELIMIT_HEADERS_ENABLED'] = True
```

---

## Deployment Configuration

### Gunicorn WSGI Server

**systemd Service:** `/etc/systemd/system/nordabiznes.service`

```ini
[Unit]
Description=Norda Biznes Hub
After=network.target postgresql.service

[Service]
Type=notify
User=www-data
Group=www-data
WorkingDirectory=/var/www/nordabiznes
Environment="PATH=/var/www/nordabiznes/venv/bin"
ExecStart=/var/www/nordabiznes/venv/bin/gunicorn \
    --workers 4 \
    --bind 127.0.0.1:5000 \
    --timeout 120 \
    --access-logfile /var/log/nordabiznes/access.log \
    --error-logfile /var/log/nordabiznes/error.log \
    app:app

Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
```

**Key Settings:**
- **Workers:** 4 (2 × CPU cores + 1)
- **Bind:** 127.0.0.1:5000 (localhost only, NPM proxies from external)
- **Timeout:** 120 seconds (for long AI requests)
- **User:** www-data (non-root for security)

**Service Management:**
```bash
# Start service
sudo systemctl start nordabiznes

# Stop service
sudo systemctl stop nordabiznes

# Restart service
sudo systemctl restart nordabiznes

# Check status
sudo systemctl status nordabiznes

# View logs
sudo journalctl -u nordabiznes -f
```

---

## Logging and Monitoring

### Application Logging

**Configuration:**
```python
import logging

# Production logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('/var/log/nordabiznes/app.log'),
        logging.StreamHandler()
    ]
)

logger = logging.getLogger(__name__)
```

**Log Locations:**
- **Application:** `/var/log/nordabiznes/app.log`
- **Gunicorn Access:** `/var/log/nordabiznes/access.log`
- **Gunicorn Error:** `/var/log/nordabiznes/error.log`
- **systemd:** `journalctl -u nordabiznes`

**Log Levels:**
- **DEBUG:** Development only, verbose output
- **INFO:** General information (startup, shutdown, API calls)
- **WARNING:** Degraded performance, fallback scenarios
- **ERROR:** Errors that don't crash the app
- **CRITICAL:** Errors that crash the app

### Health Check Endpoint

**Route:** `/health`
**Method:** GET
**Authentication:** None (public)

**Response:**
```json
{
  "status": "healthy",
  "database": "connected",
  "timestamp": "2026-01-10T12:00:00Z",
  "version": "1.0.0"
}
```

**Usage:**
- NPM health checks
- Monitoring systems (Zabbix, Prometheus)
- Uptime monitoring (UptimeRobot)
- Load balancer health checks

---

## Security Features

### 1. Authentication Security
- **Password Hashing:** bcrypt (cost factor 12)
- **Session Security:** httponly, secure, samesite cookies
- **Email Verification:** Required before login
- **Password Reset:** Time-limited tokens (1 hour expiry)
- **Account Lockout:** (Planned) After 5 failed attempts

### 2. Authorization
- **Three Levels:** Public, User, Admin
- **Decorator Pattern:** `@login_required`, `@admin_required`
- **Object-Level:** Company owners can edit their profiles

### 3. Input Validation
- **CSRF Protection:** All POST/PUT/DELETE requests
- **XSS Prevention:** Jinja2 auto-escaping
- **SQL Injection:** SQLAlchemy parameterized queries
- **File Upload:** Whitelist extensions, size limits

### 4. API Security
- **Rate Limiting:** 200/day global, 100/day chat
- **API Keys:** Environment variables only
- **CORS:** Disabled by default
- **HTTPS Only:** All API calls to external services

### 5. Database Security
- **Localhost Only:** PostgreSQL accepts only 127.0.0.1 connections
- **Password Auth:** Strong passwords for DB users
- **Least Privilege:** Application user has limited permissions
- **No Root Access:** Application runs as www-data user

---

## Related Documentation

### Higher-Level Diagrams
- [System Context Diagram (C4 Level 1)](./01-system-context.md) - External actors and systems
- [Container Diagram (C4 Level 2)](./02-container-diagram.md) - Major containers and technology stack

### Same-Level Diagrams
- [Database Schema Diagram](./05-database-schema.md) - (Planned) Detailed ER diagram
- [External Integrations Diagram](./06-external-integrations.md) - (Planned) API integration details

### Lower-Level Documentation
- [Data Flow Diagrams](./flows/) - (Planned) Sequence diagrams for key flows
- [API Endpoints Reference](./10-api-endpoints.md) - (Planned) Complete API documentation

### Infrastructure Documentation
- [Deployment Architecture](./03-deployment-architecture.md) - Servers, network, ports
- [Network Topology](./07-network-topology.md) - (Planned) Network diagram
- [Critical Configurations](./08-critical-configurations.md) - (Planned) NPM, SSL, etc.

### Analysis Documents (Phase 1)
- [Flask Application Structure Analysis](../.auto-claude/specs/003-.../analysis/flask-application-structure.md) - Detailed code analysis
- [Database Schema Analysis](../.auto-claude/specs/003-.../analysis/database-schema.md) - Database deep dive
- [External API Integrations Analysis](../.auto-claude/specs/003-.../analysis/external-api-integrations.md) - API details
- [Data Flows Analysis](../.auto-claude/specs/003-.../analysis/data-flows.md) - Flow documentation

---

## Maintenance Notes

### When to Update This Diagram

Update this document when:
- **New routes** are added to `app.py`
- **New service modules** are created
- **Database models** are added or significantly changed
- **Major refactoring** of component structure
- **New external API** integrations
- **Authentication/authorization** logic changes

### What NOT to Update Here

Don't update for:
- Bug fixes that don't change architecture
- Template content changes
- CSS/JS styling updates
- Minor field additions to existing models
- Configuration value changes

### Review Frequency

- **Quarterly** review during architecture meetings
- **After major releases** (version bumps)
- **Before onboarding** new developers

---

## Glossary

**C4 Model**
- Software architecture diagramming approach with 4 levels: Context, Container, Component, Code

**Flask**
- Python web framework for building web applications

**SQLAlchemy**
- Object-Relational Mapping (ORM) library for Python

**Gunicorn**
- WSGI HTTP server for Python applications

**WSGI**
- Web Server Gateway Interface, Python web application standard

**ORM**
- Object-Relational Mapping, database abstraction layer

**FTS**
- Full-Text Search, PostgreSQL text search feature

**pg_trgm**
- PostgreSQL extension for fuzzy text matching using trigrams

**Jinja2**
- Template engine for Python (used by Flask)

**bcrypt**
- Password hashing algorithm

**CSRF**
- Cross-Site Request Forgery, web security vulnerability

**XSS**
- Cross-Site Scripting, web security vulnerability

**Rate Limiting**
- Controlling request frequency to prevent abuse

**Streaming Response**
- Sending response data in chunks (used for AI chat)

---

**Document Status:** ✅ Complete
**Last Reviewed:** 2026-01-10
**Next Review:** 2026-04-10 (Quarterly)
