# System-Architektur: Risk Intelligence Platform

## 📋 Inhaltsverzeichnis

1. [Übersicht](#übersicht)
2. [System-Diagramm](#system-diagramm)
3. [Technologie-Stack](#technologie-stack)
4. [Datenbank-Architektur](#datenbank-architektur)
5. [Datenfluss & ETL-Pipeline](#datenfluss--etl-pipeline)
6. [Applikations-Schichten](#applikations-schichten)
7. [Frontend-Architektur](#frontend-architektur)
8. [Backend-Integration](#backend-integration)
9. [Scheduling & Automation](#scheduling--automation)
10. [Sicherheit & Authentication](#sicherheit--authentication)
11. [Deployment-Architektur](#deployment-architektur)

---

## Übersicht

Die **Risk Intelligence Platform** ist eine Laravel-basierte Web-Applikation zur Analyse und Bewertung von Unternehmenstransaktionen hinsichtlich KYC (Know Your Customer) und Compliance-Risiken.

### Kernfunktionen

- ✅ **Unternehmenssuche & -bewertung** mit KYC Risk Levels
- ✅ **Transaktionsanalyse** mit 139 Datenfeldern (37 Core + 102 JSONB)
- ✅ **Automatische Backend-Synchronisation** (ETL-Pipeline)
- ✅ **Risk Score Berechnung** basierend auf Multi-Faktoren-Analyse
- ✅ **Compliance-Checks** (EU/OFAC/UK Sanctions, PEP, AML)
- ✅ **Benutzer-Authentication** mit 2FA-Unterstützung

### Zielgruppe

- Compliance-Teams
- Risk Analysts
- KYC-Spezialisten

---

## System-Diagramm

```
┌─────────────────────────────────────────────────────────────────────────┐
│                           FRONTEND (Browser)                            │
│                    Livewire Volt Components + Flux UI                   │
└─────────────────────────┬───────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                      LARAVEL APPLICATION                                │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────────┐    │
│  │   Controllers   │  │  Livewire Volt  │  │   API Endpoints     │    │
│  │   (Minimal)     │  │   Components    │  │   (Future)          │    │
│  └────────┬────────┘  └────────┬────────┘  └─────────────────────┘    │
│           │                    │                                        │
│           ▼                    ▼                                        │
│  ┌─────────────────────────────────────────────┐                       │
│  │           Eloquent Models & Repositories     │                       │
│  │   Company │ Transaction │ User               │                       │
│  └──────────────────┬──────────────────────────┘                       │
│                     │                                                   │
│           ┌─────────┴─────────┐                                        │
│           ▼                   ▼                                        │
│  ┌──────────────────┐  ┌──────────────────┐                           │
│  │   Jobs/Queue     │  │    Services      │                           │
│  │  - SyncDataPool  │  │  - KycRiskCalc   │                           │
│  │  - Transform     │  │  - DataExtract   │                           │
│  └──────────────────┘  └──────────────────┘                           │
└────────────┬────────────────────────────────────────────────────────────┘
             │
             ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                    POSTGRESQL DATABASE (Port 5433)                      │
│  ┌───────────────────────────────────────────────────────────────┐     │
│  │  Schema: PUBLIC (Default Connection)                          │     │
│  │  ┌─────────────┐  ┌──────────────────┐  ┌─────────────────┐  │     │
│  │  │  companies  │  │   transactions   │  │ backend_data_   │  │     │
│  │  │             │  │   (139 cols)     │  │      pool       │  │     │
│  │  │  - name     │◄─┤  - company_id    │  │                 │  │     │
│  │  │  - kyc_risk │  │  - risk_score    │  │  - transaction_ │  │     │
│  │  │  - sector   │  │  - 102 JSONB cols│  │       id        │  │     │
│  │  └─────────────┘  └──────────────────┘  │  - output_key   │  │     │
│  │                                          │  - content      │  │     │
│  │                                          └─────────────────┘  │     │
│  └───────────────────────────────────────────────────────────────┘     │
│                                                                         │
│  ┌───────────────────────────────────────────────────────────────┐     │
│  │  Schema: BACKEND (Backend Connection)                         │     │
│  │  ┌──────────────────┐  ┌──────────────────────────────────┐  │     │
│  │  │   transactions   │  │  transaction_outputs             │  │     │
│  │  │                  │  │                                  │  │     │
│  │  │  - id            │◄─┤  - transaction_id                │  │     │
│  │  │  - status        │  │  - prompt_id                     │  │     │
│  │  │  - tx_amount     │  │  - output_key                    │  │     │
│  │  │  - risk_score    │  │  - content (JSONB)               │  │     │
│  │  └──────────────────┘  └──────────────────────────────────┘  │     │
│  └───────────────────────────────────────────────────────────────┘     │
└─────────────────────────────────────────────────────────────────────────┘
             ▲
             │
             │ (ETL Pipeline - Scheduled Jobs)
             │
┌────────────┴────────────────────────────────────────────────────────────┐
│                    LARAVEL SCHEDULER (Cron)                             │
│  ┌─────────────────────────────────────────────────────────────┐       │
│  │  Every 6h (0:00, 6:00, 12:00, 18:00):                       │       │
│  │    → SyncBackendDataPool (Incremental)                      │       │
│  │                                                              │       │
│  │  Every 6h (0:30, 6:30, 12:30, 18:30):                       │       │
│  │    → TransformDataPoolToProduction                          │       │
│  │                                                              │       │
│  │  Sunday 3:00:                                                │       │
│  │    → SyncBackendDataPool (Full Rebuild)                     │       │
│  └─────────────────────────────────────────────────────────────┘       │
└─────────────────────────────────────────────────────────────────────────┘
```

---

## Technologie-Stack

### Backend

| Komponente | Version | Zweck |
|-----------|---------|-------|
| **PHP** | 8.4.14 | Runtime |
| **Laravel Framework** | 12.x | Application Framework |
| **PostgreSQL** | Latest | Primäre Datenbank |
| **Laravel Fortify** | 1.x | Authentication |
| **Livewire** | 3.x | Reactive Components |
| **Livewire Volt** | 1.x | Single-File Components |

### Frontend

| Komponente | Version | Zweck |
|-----------|---------|-------|
| **Flux UI** | 2.x (Free) | Component Library |
| **Tailwind CSS** | 4.x | Styling Framework |
| **Alpine.js** | Latest (via Livewire) | JavaScript Interactivity |
| **Vite** | Latest | Asset Bundling |

### Development & Testing

| Komponente | Version | Zweck |
|-----------|---------|-------|
| **Pest** | 4.x | Testing Framework |
| **PHPUnit** | 12.x | Unit Testing |
| **Laravel Pint** | 1.x | Code Formatting |
| **Laravel Sail** | 1.x | Docker Development |
| **Laravel Boost** | 1.4+ | MCP Server (Development) |

### Infrastructure

- **Docker** - Containerization
- **Kubernetes** - Orchestration (k8s-cronjob.yaml)
- **Cron** - Scheduling (Laravel Scheduler)
- **Queue System** - Asynchronous Jobs

---

## Datenbank-Architektur

### Verbindungen

Die Applikation nutzt **eine PostgreSQL-Datenbank** mit **zwei Schemas**:

```php
// config/database.php

'default' => 'pgsql_second',  // Default: public schema

'connections' => [
    // Frontend Schema (Production Tables)
    'pgsql_second' => [
        'search_path' => 'public',
        'port' => env('DB_PORT2', 5432),
        'database' => env('DB_DATABASE2'),
    ],

    // Backend Schema (Source Data)
    'backend' => [
        'search_path' => 'backend',
        'port' => env('DB_PORT2', 5432),
        'database' => env('DB_DATABASE2'),  // Same DB, different schema
    ],
]
```

### Schema: PUBLIC (Production)

#### Companies Tabelle
```sql
CREATE TABLE public.companies (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    legal_name VARCHAR(255),
    ticker VARCHAR(50),
    sector VARCHAR(100),
    country VARCHAR(2),              -- ISO 3166-1 alpha-2
    headquarters TEXT,
    kyc_risk_level VARCHAR(20),      -- low | high | critical
    summary TEXT,
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);
```

#### Transactions Tabelle (139 Spalten)

**Core Felder (37):**
```sql
CREATE TABLE public.transactions (
    -- Identity & Relationships
    id SERIAL PRIMARY KEY,
    company_id INTEGER REFERENCES companies(id),
    reference VARCHAR(255) UNIQUE NOT NULL,

    -- Transaction Details
    amount DECIMAL(15,2),
    currency VARCHAR(3),
    counterparty VARCHAR(255),
    counterparty_country VARCHAR(2),
    channel VARCHAR(50),
    executed_at TIMESTAMP,

    -- Risk Assessment
    risk_score INTEGER,              -- 0-255 normalized
    status VARCHAR(50),              -- true_positive | false_positive | cleared
    requires_review BOOLEAN,
    flagged_by VARCHAR(255),
    flagged_reason TEXT,
    signals JSONB,

    -- Additional Entity Data
    entity VARCHAR(255),             -- Corporate entity name
    counterparty_kyc_risk_level VARCHAR(20),

    -- Risk Breakdown
    transaction_risk_score INTEGER,
    sanctions_risk_score INTEGER,
    country_risk_score INTEGER,
    pep_adverse_risk_score INTEGER,
    corruption_risk_score INTEGER,

    -- Timestamps
    created_at TIMESTAMP,
    updated_at TIMESTAMP,

    -- ... 102 JSONB Columns (siehe unten)
);
```

**JSONB Output Columns (102):**

Alle `output_key` Werte aus `backend.transaction_outputs` werden als JSONB-Spalten gespeichert:

<details>
<summary>Vollständige Liste der 102 JSONB Spalten (klicken zum Ausklappen)</summary>

**Corporate Information:**
- `corporate_summary`
- `corporate_history`
- `corporate_legalname`
- `corporate_sector`
- `corporate_HQ`
- `corporate_keyexecs`
- `corporate_shareholding`
- `corporate_parentcompany`
- `corporate_subsidiaries`
- `corporate_countryofincorporation`
- `corporate_ticker`
- `corporate_counterparty`
- `corporate_counterpartysector`
- `corporate_counterpartycountry`
- `corporate_counterpartysummary`
- `corporate_counterpartyhistory`

**Sanctions & Compliance:**
- `corporate_eusanctions`
- `corporate_ofacsanctions`
- `corporate_uksanctions`
- `corporate_pepexposure`
- `corporate_AMLexposure`
- `corporate_adverse`
- `sanctions_circumvention`

**Country Risk:**
- `country_risk`
- `country_name`
- `country_iso2`
- `country_iso3`
- `country_cpi`
- `country_euprivacy`
- `country_dataprivacy`
- `country_gdpr`
- `country_sanctions`
- `country_wgi`
- `country_pep`

**Corruption:**
- `corruption_sector`
- `corruption_country`
- `corruption_relationship`

**Financial & Transaction:**
- `tranx_score`
- `tranx_reasoning`
- `tranx_amount`
- `tranx_currency`
- `tranx_date`
- `tranx_counterparty`
- `tranx_channel`
- `financial_assessment`

... und weitere 60+ Spalten für detaillierte Analysen
</details>

#### Backend Data Pool Tabelle
```sql
CREATE TABLE public.backend_data_pool (
    id SERIAL PRIMARY KEY,

    -- Foreign Keys (Backend Schema)
    transaction_id INTEGER NOT NULL,
    prompt_id INTEGER NOT NULL,

    -- Transaction Core Data
    corporate_entity VARCHAR(255),
    tx_amount DECIMAL(15,2),
    tx_currency VARCHAR(3),
    tx_date DATE,
    status VARCHAR(50),

    -- Risk Scores
    risk_score INTEGER,              -- Backend risk_score (-100 to 100)

    -- Output Data
    output_key VARCHAR(255),
    content JSONB,

    -- Metadata
    synced_at TIMESTAMP DEFAULT NOW(),

    UNIQUE(transaction_id, prompt_id)
);

CREATE INDEX idx_backend_data_pool_transaction_id ON backend_data_pool(transaction_id);
CREATE INDEX idx_backend_data_pool_output_key ON backend_data_pool(output_key);
```

### Schema: BACKEND (Source Data)

#### Backend Transactions
```sql
CREATE TABLE backend.transactions (
    id SERIAL PRIMARY KEY,
    corporate_entity VARCHAR(255),
    tx_amount DECIMAL(15,2),
    tx_currency VARCHAR(3),
    tx_date DATE,
    status VARCHAR(50),            -- pending | processing | done | failed
    risk_score INTEGER,            -- -100 to 100 (Backend Scale)
    last_modified_at TIMESTAMP,
    created_at TIMESTAMP
);
```

#### Backend Transaction Outputs
```sql
CREATE TABLE backend.transaction_outputs (
    id SERIAL PRIMARY KEY,
    transaction_id INTEGER REFERENCES transactions(id),
    prompt_id INTEGER,
    output_key VARCHAR(255),       -- z.B. "corporate_summary", "tranx_score"
    content JSONB,                 -- LLM-Generated Output
    created_at TIMESTAMP,

    UNIQUE(transaction_id, prompt_id)
);
```

---

## Datenfluss & ETL-Pipeline

### Dreistufiger Datenprozess

```
┌─────────────────────────────────────────────────────────────┐
│ STUFE 0: Backend Processing (Extern)                       │
│                                                             │
│  LLM Analysis → backend.transactions                       │
│              → backend.transaction_outputs                 │
└─────────────┬───────────────────────────────────────────────┘
              │
              ▼
┌─────────────────────────────────────────────────────────────┐
│ STUFE 1: Data Pool Sync                                    │
│                                                             │
│  Job: SyncBackendDataPool                                  │
│  Schedule: Every 6h (Incremental) | Sunday 3am (Full)      │
│                                                             │
│  Source:  backend.transactions                             │
│          + backend.transaction_outputs                     │
│                                                             │
│  Target:  public.backend_data_pool                         │
│                                                             │
│  Process:                                                   │
│  1. Query backend schema (WHERE status='done')             │
│  2. Join transactions + outputs                            │
│  3. Batch insert into data pool (1000 records/batch)       │
│  4. Track sync timestamp                                   │
│                                                             │
│  Performance:                                               │
│  - Full Sync: ~30-60s (7,471 records)                      │
│  - Incremental: ~5-10s (new records only)                  │
└─────────────┬───────────────────────────────────────────────┘
              │
              ▼
┌─────────────────────────────────────────────────────────────┐
│ STUFE 2: Production Transformation                         │
│                                                             │
│  Job: TransformDataPoolToProduction                        │
│  Schedule: Every 6h at :30 (30min after Sync)              │
│                                                             │
│  Source:  public.backend_data_pool                         │
│                                                             │
│  Targets: public.companies                                 │
│          + public.transactions                             │
│                                                             │
│  Process:                                                   │
│  1. Group by transaction_id                                │
│  2. For each transaction:                                  │
│     a) Extract/Update Company (by corporate_entity)        │
│        - Calculate KYC Risk Level                          │
│        - Enrich with sector, country, HQ                   │
│     b) Create/Update Transaction                           │
│        - Map all 139 columns                               │
│        - Link to company_id                                │
│        - Transform risk_score (-100..100 → 0..255)         │
│  3. Batch process (100 records/batch)                      │
│                                                             │
│  Features:                                                  │
│  - Idempotent (updateOrCreate)                             │
│  - Deduplication by reference                              │
│  - Risk Score Normalization                                │
│                                                             │
│  Performance:                                               │
│  - Initial: ~30-60s (74 transactions → ~70 companies)      │
│  - Updates: ~5-10s                                         │
└─────────────┬───────────────────────────────────────────────┘
              │
              ▼
┌─────────────────────────────────────────────────────────────┐
│ STUFE 3: Frontend Display (Real-time)                      │
│                                                             │
│  Livewire Volt Components query:                           │
│  - public.companies                                        │
│  - public.transactions                                     │
│                                                             │
│  No additional processing required                         │
└─────────────────────────────────────────────────────────────┘
```

### Risk Score Transformation

Backend nutzt eine Skala von **-100 bis 100**, Frontend **0 bis 255**:

```php
// Backend → Frontend Normalization
$normalizedScore = (($backendScore + 100) / 200) * 255;

// Beispiele:
// Backend: -100 → Frontend: 0    (Sehr gut)
// Backend: 0    → Frontend: 127  (Neutral)
// Backend: 100  → Frontend: 255  (Sehr schlecht)
```

**Risk Level Mapping:**

| Backend Score | Frontend Score | Risk Level | Transaction Status |
|--------------|----------------|------------|-------------------|
| -100 to 20   | 0 to 153       | `low`      | `cleared` |
| 20 to 80     | 153 to 229     | `high`     | `false_positive` |
| 80 to 100    | 229 to 255     | `critical` | `true_positive` |

---

## Applikations-Schichten

### Layer Architecture

```
┌──────────────────────────────────────────────────────┐
│  PRESENTATION LAYER                                  │
│  - Livewire Volt Components (resources/views/       │
│                               livewire/)             │
│  - Blade Templates                                   │
│  - Flux UI Components                                │
└──────────────────┬───────────────────────────────────┘
                   │
                   ▼
┌──────────────────────────────────────────────────────┐
│  APPLICATION LAYER                                   │
│  - Controllers (minimal, mostly Volt)                │
│  - Livewire Actions (app/Livewire/Actions/)         │
│  - Form Requests (validation)                        │
└──────────────────┬───────────────────────────────────┘
                   │
                   ▼
┌──────────────────────────────────────────────────────┐
│  DOMAIN LAYER                                        │
│  - Eloquent Models (app/Models/)                     │
│    · Company                                         │
│    · Transaction                                     │
│    · User                                            │
│    · Backend\Transaction                             │
│    · Backend\TransactionOutput                       │
│  - Repositories (app/Repositories/)                  │
│    · TransactionRepository                           │
│  - Services (app/Services/)                          │
│    · KycRiskCalculator                               │
└──────────────────┬───────────────────────────────────┘
                   │
                   ▼
┌──────────────────────────────────────────────────────┐
│  INFRASTRUCTURE LAYER                                │
│  - Jobs (app/Jobs/)                                  │
│    · SyncBackendDataPool                             │
│    · TransformDataPoolToProduction                   │
│  - Commands (app/Console/Commands/)                  │
│    · SyncBackendDataPoolCommand                      │
│    · TransformDataPoolCommand                        │
│    · RebuildFromDataPoolCommand                      │
│  - Database Migrations                               │
│  - Schedulers (routes/console.php)                   │
└──────────────────────────────────────────────────────┘
```

---

## Frontend-Architektur

### Livewire Volt Components

Die Applikation nutzt **Single-File Components** mit Livewire Volt:

```php
// resources/views/livewire/company-search.blade.php
<?php

use Livewire\Volt\Component;
use App\Models\Company;

new class extends Component {
    public string $search = '';

    public function with(): array
    {
        return [
            'companies' => Company::query()
                ->when($this->search, fn($q) =>
                    $q->where('name', 'ilike', "%{$this->search}%")
                )
                ->limit(20)
                ->get(),
        ];
    }
}
?>

<div>
    <flux:input wire:model.live.debounce.300ms="search" />
    <!-- UI -->
</div>
```

### Routen-Struktur

```php
// routes/web.php

// Public
Route::get('/', fn() => view('welcome'))->name('home');

// Authenticated Routes
Route::middleware(['auth', 'verified'])->group(function () {
    Route::view('dashboard', 'dashboard')->name('dashboard');

    // Volt Routes
    Volt::route('company-search', 'company-search')->name('company-search');
    Volt::route('transaction-review', 'transaction-review')->name('transaction-review');
    Volt::route('companies/{company}/transactions', 'companies.transactions')
        ->name('company.transactions');
    Volt::route('upload', 'upload.index')->name('upload');

    // Settings
    Volt::route('settings/profile', 'settings.profile')->name('profile.edit');
    Volt::route('settings/password', 'settings.password')->name('password.edit');
    Volt::route('settings/two-factor', 'settings.two-factor')
        ->middleware(['password.confirm'])
        ->name('two-factor.show');
});
```

### Hauptseiten

| Route | Component | Beschreibung |
|-------|-----------|--------------|
| `/` | welcome.blade.php | Landing Page |
| `/dashboard` | dashboard.blade.php | Dashboard-Übersicht |
| `/company-search` | company-search.blade.php | Unternehmenssuche |
| `/transaction-review` | transaction-review.blade.php | Transaktionsübersicht |
| `/companies/{id}/transactions` | companies.transactions.blade.php | Company-Detail mit Transactions |
| `/upload` | upload.index.blade.php | Upload-Funktionalität |

---

## Backend-Integration

### Models & Relationships

```php
// app/Models/Company.php
class Company extends Model
{
    protected $fillable = [
        'name', 'legal_name', 'ticker', 'sector',
        'country', 'headquarters', 'kyc_risk_level', 'summary',
    ];

    public function transactions(): HasMany
    {
        return $this->hasMany(Transaction::class);
    }
}

// app/Models/Transaction.php
class Transaction extends Model
{
    protected $guarded = [];  // Allow all (for 102 JSONB columns)

    // Dynamic JSONB casting
    protected function casts(): array
    {
        $allColumns = Schema::getColumnListing('transactions');
        $jsonbColumns = array_diff($allColumns, $standardColumns);

        foreach ($jsonbColumns as $column) {
            $casts[$column] = 'array';
        }

        return $casts;
    }

    public function company(): BelongsTo
    {
        return $this->belongsTo(Company::class);
    }
}
```

### Jobs

#### SyncBackendDataPool

```php
// app/Jobs/SyncBackendDataPool.php

class SyncBackendDataPool implements ShouldQueue
{
    public function __construct(
        public bool $fullSync = false,
        public int $batchSize = 1000,
    ) {}

    public function handle(): void
    {
        if ($this->fullSync) {
            DB::table('backend_data_pool')->truncate();
        }

        $query = DB::connection('pgsql')
            ->table('backend.transactions as t')
            ->join('backend.transaction_outputs as tout', 't.id', '=', 'tout.transaction_id')
            ->where('t.status', 'done')
            ->select([
                't.id as transaction_id',
                'tout.prompt_id',
                't.corporate_entity',
                't.tx_amount',
                't.tx_currency',
                't.tx_date',
                't.status',
                't.risk_score',
                'tout.output_key',
                'tout.content',
            ]);

        $query->chunk($this->batchSize, function ($records) {
            DB::table('backend_data_pool')->insert(
                $records->map(fn($r) => [
                    ...(array) $r,
                    'synced_at' => now(),
                ])->toArray()
            );
        });
    }
}
```

#### TransformDataPoolToProduction

```php
// app/Jobs/TransformDataPoolToProduction.php

class TransformDataPoolToProduction implements ShouldQueue
{
    public function handle(): void
    {
        $transactionIds = DB::table('backend_data_pool')
            ->distinct()
            ->pluck('transaction_id');

        foreach ($transactionIds as $transactionId) {
            $outputs = DB::table('backend_data_pool')
                ->where('transaction_id', $transactionId)
                ->get();

            $company = $this->createOrUpdateCompany($outputs);
            $this->createOrUpdateTransaction($company, $outputs);
        }
    }

    private function createOrUpdateCompany($outputs): Company
    {
        $first = $outputs->first();

        return Company::updateOrCreate(
            ['name' => $first->corporate_entity],
            [
                'sector' => $this->extractValue($outputs, 'corporate_sector'),
                'country' => $this->extractValue($outputs, 'corporate_countryofincorporation'),
                'headquarters' => $this->extractValue($outputs, 'corporate_HQ'),
                'kyc_risk_level' => $this->calculateKycRiskLevel($first->risk_score),
                'summary' => $this->extractValue($outputs, 'corporate_summary'),
            ]
        );
    }
}
```

### Commands

```bash
# Manuelle Sync-Commands
php artisan backend:sync-data-pool --full
php artisan backend:sync-data-pool --incremental
php artisan backend:transform-data-pool
php artisan backend:rebuild  # Full Sync + Transform
```

---

## Scheduling & Automation

### Laravel Scheduler Configuration

```php
// routes/console.php

// Incremental Sync: 0:00, 6:00, 12:00, 18:00
Schedule::job(new SyncBackendDataPool(fullSync: false, batchSize: 1000))
    ->everySixHours()
    ->name('sync-backend-data-pool-incremental')
    ->withoutOverlapping(1800);

// Full Sync: Sonntag 3:00 Uhr
Schedule::job(new SyncBackendDataPool(fullSync: true, batchSize: 1000))
    ->weeklyOn(0, '03:00')
    ->name('sync-backend-data-pool-full')
    ->withoutOverlapping(3600);

// Transformation: 0:30, 6:30, 12:30, 18:30
Schedule::job(new TransformDataPoolToProduction(batchSize: 100))
    ->cron('30 */6 * * *')
    ->name('transform-data-pool-to-production')
    ->withoutOverlapping(1800);
```

### Aktivierung

#### Lokale Entwicklung
```bash
php artisan schedule:work
```

#### Produktion (Crontab)
```bash
crontab -e

# Füge hinzu:
* * * * * cd /path/to/project && php artisan schedule:run >> /dev/null 2>&1
```

#### Mit Supervisor
```ini
[program:laravel-scheduler]
command=php /path/to/project/artisan schedule:work
autostart=true
autorestart=true
```

---

## Sicherheit & Authentication

### Laravel Fortify

Die Applikation nutzt **Laravel Fortify** für Authentication:

```php
// config/fortify.php - Enabled Features

Features::registration(),
Features::resetPasswords(),
Features::emailVerification(),
Features::updateProfileInformation(),
Features::updatePasswords(),
Features::twoFactorAuthentication([
    'confirm' => true,
    'confirmPassword' => true,
]),
```

### Two-Factor Authentication (2FA)

- QR-Code basierte 2FA mit TOTP
- Recovery Codes
- Passwort-Bestätigung erforderlich

### Authorization

- Route Middleware: `auth`, `verified`
- Password Confirmation für sensible Aktionen

### Session Management

- Standard Laravel Session-Driver
- CSRF Protection aktiviert

---

## Deployment-Architektur

### Docker Setup

```yaml
# docker-compose.yml

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8000:8000"
    volumes:
      - .:/var/www/html
    environment:
      - DB_CONNECTION2=pgsql
      - DB_HOST2=db
      - DB_PORT2=5432
```

### Kubernetes CronJob

```yaml
# k8s-cronjob.yaml

apiVersion: batch/v1
kind: CronJob
metadata:
  name: backend-sync
spec:
  schedule: "0 */6 * * *"  # Every 6 hours
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: sync
            image: risk-platform:latest
            command: ["php", "artisan", "backend:sync-data-pool", "--incremental"]
```

### Environment Configuration

```bash
# .env (Production)

APP_ENV=production
APP_DEBUG=false

DB_CONNECTION2=pgsql
DB_HOST2=postgres.internal
DB_PORT2=5432
DB_DATABASE2=risk_platform_db
DB_USERNAME2=risk_user
DB_PASSWORD2=***

CACHE_STORE=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
```

### Scaling Considerations

**Horizontal Scaling:**
- Stateless Laravel App → Load Balancer → Multiple App Instances
- Shared Redis für Sessions/Cache
- Shared PostgreSQL Cluster

**Performance Optimization:**
- Redis Caching für Companies/Transactions
- Database Indexing (transaction_id, output_key, company_id)
- Query Optimization mit Eager Loading
- CDN für Static Assets

---

## Monitoring & Logging

### Laravel Logs

```bash
# Application Logs
tail -f storage/logs/laravel.log

# Nur Sync-Logs
tail -f storage/logs/laravel.log | grep SyncBackendDataPool

# Nur Transform-Logs
tail -f storage/logs/laravel.log | grep TransformDataPoolToProduction
```

### Queue Monitoring

```bash
php artisan queue:work --tries=3
php artisan queue:monitor
```

### Database Performance Monitoring

```sql
-- Sync-Performance (Records pro Minute)
SELECT
    DATE_TRUNC('minute', synced_at) as minute,
    COUNT(*) as records_synced
FROM public.backend_data_pool
WHERE synced_at >= NOW() - INTERVAL '1 hour'
GROUP BY DATE_TRUNC('minute', synced_at)
ORDER BY minute DESC;
```

### Optional: Laravel Telescope

```bash
composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate
```

---

## Zusammenfassung

### System-Eigenschaften

✅ **Monolithische Laravel-Applikation** mit klarer Layer-Trennung
✅ **ETL-Pipeline** mit zweistufiger Transformation (Sync → Transform)
✅ **Automatisierung** via Laravel Scheduler (alle 6h)
✅ **Reactive Frontend** mit Livewire Volt + Flux UI
✅ **Skalierbar** via Queue-System und horizontaler App-Skalierung
✅ **Sicher** mit Fortify Authentication + 2FA
✅ **Testbar** mit Pest Testing Framework

### Performance-Metriken

| Operation | Datenmenge | Dauer | Frequenz |
|-----------|-----------|-------|----------|
| Incremental Sync | ~100-500 Records | 5-10s | Alle 6h |
| Full Sync | 7,471 Records | 30-60s | Sonntag 3am |
| Transformation | 74 Transactions | 30-60s | Alle 6h (30min nach Sync) |
| Page Load (Companies) | 20 Records | <100ms | On Demand |

### Nächste Schritte

- [ ] API-Dokumentation (OpenAPI/Swagger)
- [ ] Testing-Guide & Coverage-Ziele
- [ ] Deployment-Runbooks
- [ ] Entwickler-Onboarding-Guide
- [ ] Performance-Optimierung (Caching-Strategie)

---

**Erstellt:** 2025-11-24
**Version:** 1.0
**Autor:** Risk Intelligence Platform Team
