# 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:
VollstΓ€ndige Liste der 102 JSONB Spalten (klicken zum Ausklappen)
**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
#### 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
Company::query()
->when($this->search, fn($q) =>
$q->where('name', 'ilike', "%{$this->search}%")
)
->limit(20)
->get(),
];
}
}
?>
```
### 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