local-docker-db branch openend
Build and Push Docker Image only on Conventional Commits / build (push) Has been cancelled
Build and Push Docker Image only on Conventional Commits / build (push) Has been cancelled
This commit is contained in:
@@ -27,15 +27,15 @@ LOG_LEVEL=debug
|
||||
# DB_USERNAME=root
|
||||
# DB_PASSWORD=
|
||||
|
||||
# Secondary PostgreSQL Connection (for backend schema)
|
||||
# Secondary PostgreSQL Connection (for backend schema) - Local Docker
|
||||
DB_CONNECTION2=pgsql
|
||||
DB_HOST2=127.0.0.1
|
||||
DB_PORT2=5433
|
||||
DB_DATABASE2=risk_ingest_db
|
||||
DB_USERNAME2=risk_ingest_user
|
||||
DB_PASSWORD2=S0prast3r1a
|
||||
DB_PORT2=5432
|
||||
DB_DATABASE2=ingest_db
|
||||
DB_USERNAME2=ingest_user
|
||||
DB_PASSWORD2=ingest_pwd
|
||||
|
||||
SESSION_DRIVER=database
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
SESSION_ENCRYPT=false
|
||||
SESSION_PATH=/
|
||||
@@ -43,9 +43,9 @@ SESSION_DOMAIN=null
|
||||
|
||||
BROADCAST_CONNECTION=log
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=database
|
||||
QUEUE_CONNECTION=sync
|
||||
|
||||
CACHE_STORE=database
|
||||
CACHE_STORE=file
|
||||
# CACHE_PREFIX=
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+10
-10
@@ -86,10 +86,10 @@ return [
|
||||
'driver' => 'pgsql',
|
||||
'url' => env('DB_URL'),
|
||||
'host' => env('DB_HOST2', '127.0.0.1'),
|
||||
'port' => env('DB_PORT2', '5433'),
|
||||
'database' => env('DB_DATABASE2', 'risk_ingest_db'),
|
||||
'username' => env('DB_USERNAME2', 'risk_ingest_user'),
|
||||
'password' => env('DB_PASSWORD2', ''),
|
||||
'port' => env('DB_PORT2', '5432'),
|
||||
'database' => env('DB_DATABASE2', 'ingest_db'),
|
||||
'username' => env('DB_USERNAME2', 'ingest_user'),
|
||||
'password' => env('DB_PASSWORD2', 'ingest_pwd'),
|
||||
'charset' => env('DB_CHARSET', 'utf8'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
@@ -101,9 +101,9 @@ return [
|
||||
'driver' => env('DB_CONNECTION2'),
|
||||
'host' => env('DB_HOST2', '127.0.0.1'),
|
||||
'port' => env('DB_PORT2', '5432'),
|
||||
'database' => env('DB_DATABASE2', 'laravel'),
|
||||
'username' => env('DB_USERNAME2', 'root'),
|
||||
'password' => env('DB_PASSWORD2', ''),
|
||||
'database' => env('DB_DATABASE2', 'ingest_db'),
|
||||
'username' => env('DB_USERNAME2', 'ingest_user'),
|
||||
'password' => env('DB_PASSWORD2', 'ingest_pwd'),
|
||||
'charset' => env('DB_CHARSET', 'utf8'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
@@ -115,9 +115,9 @@ return [
|
||||
'driver' => env('DB_CONNECTION2'),
|
||||
'host' => env('DB_HOST2', '127.0.0.1'),
|
||||
'port' => env('DB_PORT2', '5432'),
|
||||
'database' => env('DB_DATABASE2', 'laravel'),
|
||||
'username' => env('DB_USERNAME2', 'root'),
|
||||
'password' => env('DB_PASSWORD2', ''),
|
||||
'database' => env('DB_DATABASE2', 'ingest_db'),
|
||||
'username' => env('DB_USERNAME2', 'ingest_user'),
|
||||
'password' => env('DB_PASSWORD2', 'ingest_pwd'),
|
||||
'charset' => env('DB_CHARSET', 'utf8'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
|
||||
@@ -0,0 +1,999 @@
|
||||
# API-Dokumentation: Risk Intelligence Platform
|
||||
|
||||
## 📋 Inhaltsverzeichnis
|
||||
|
||||
1. [Übersicht](#übersicht)
|
||||
2. [API-Spezifikation](#api-spezifikation)
|
||||
3. [Authentication](#authentication)
|
||||
4. [Endpoints](#endpoints)
|
||||
5. [Datenmodelle](#datenmodelle)
|
||||
6. [Beispiele](#beispiele)
|
||||
7. [Error Handling](#error-handling)
|
||||
8. [Rate Limiting](#rate-limiting)
|
||||
9. [Changelog](#changelog)
|
||||
|
||||
---
|
||||
|
||||
## Übersicht
|
||||
|
||||
Die **Trusted AI Analyst Data API** stellt Daten für das Analyst Dashboard, Transaction Review, Company Search und Company Drill-Down bereit.
|
||||
|
||||
### API-Version
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Format:** JSON
|
||||
**Authentifizierung:** Session-basiert (Laravel Session Cookie)
|
||||
|
||||
### Base URLs
|
||||
|
||||
| Environment | URL |
|
||||
|-------------|-----|
|
||||
| **Development** | `http://trusted_ai.test/api` |
|
||||
| **Production** | `https://afc.trai.sft.comstack.de/api` |
|
||||
|
||||
### OpenAPI Spezifikation
|
||||
|
||||
Die vollständige API-Spezifikation ist in [swagger.yaml](../swagger.yaml) dokumentiert.
|
||||
|
||||
**Swagger UI:** Die Spezifikation kann mit [Swagger Editor](https://editor.swagger.io) oder Swagger UI visualisiert werden.
|
||||
|
||||
---
|
||||
|
||||
## API-Spezifikation
|
||||
|
||||
### API-Kategorien
|
||||
|
||||
| Tag | Beschreibung | Endpoints |
|
||||
|-----|--------------|-----------|
|
||||
| **Dashboard** | KPIs und Alert-Übersichten | 1 Endpoint |
|
||||
| **Transactions** | Portfolio-weite Transaction Review | 2 Endpoints |
|
||||
| **Companies** | Company Discovery & Drill-Down | 4 Endpoints |
|
||||
|
||||
**Gesamt:** 7 API-Endpoints
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
### Session-basierte Authentifizierung
|
||||
|
||||
Die API nutzt **Laravel Session Cookies** für die Authentifizierung.
|
||||
|
||||
```yaml
|
||||
securitySchemes:
|
||||
sessionCookie:
|
||||
type: apiKey
|
||||
in: cookie
|
||||
name: laravel_session
|
||||
```
|
||||
|
||||
### Login-Flow
|
||||
|
||||
1. **Login via Web-Interface:**
|
||||
```http
|
||||
POST /login HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
email=user@example.com&password=secret
|
||||
```
|
||||
|
||||
2. **Session Cookie erhalten:**
|
||||
```http
|
||||
HTTP/1.1 302 Found
|
||||
Set-Cookie: laravel_session=eyJ....; Path=/; HttpOnly; SameSite=lax
|
||||
```
|
||||
|
||||
3. **API-Request mit Cookie:**
|
||||
```http
|
||||
GET /api/dashboard/overview HTTP/1.1
|
||||
Cookie: laravel_session=eyJ....
|
||||
```
|
||||
|
||||
### Authentifizierungs-Fehler
|
||||
|
||||
```json
|
||||
HTTP/1.1 401 Unauthorized
|
||||
{
|
||||
"message": "Unauthenticated."
|
||||
}
|
||||
```
|
||||
|
||||
**Wichtig:** Alle API-Endpoints erfordern eine gültige Session!
|
||||
|
||||
---
|
||||
|
||||
## Endpoints
|
||||
|
||||
### 1. Dashboard
|
||||
|
||||
#### GET /dashboard/overview
|
||||
|
||||
Liefert aggregierte KPIs und Alert-Übersichten für das Dashboard.
|
||||
|
||||
**Request:**
|
||||
```http
|
||||
GET /api/dashboard/overview HTTP/1.1
|
||||
Cookie: laravel_session=...
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"generatedAt": "2025-01-19T07:30:00Z",
|
||||
"activeAnalysts": 24,
|
||||
"totalTransactions": 312,
|
||||
"totalVolume": 98765432.10,
|
||||
"alertsToday": 56,
|
||||
"averageAlertsPerAnalyst": 3,
|
||||
"precisionRate": 84,
|
||||
"activeAlerts": {
|
||||
"count": 128,
|
||||
"highRiskCount": 19
|
||||
},
|
||||
"riskSegments": [
|
||||
{
|
||||
"label": "Kritisch (≥80)",
|
||||
"count": 17,
|
||||
"volume": 8900000.0
|
||||
},
|
||||
{
|
||||
"label": "Hoch (60-79)",
|
||||
"count": 42,
|
||||
"volume": 15200000.0
|
||||
},
|
||||
{
|
||||
"label": "Mittel (40-59)",
|
||||
"count": 89,
|
||||
"volume": 32100000.0
|
||||
}
|
||||
],
|
||||
"topCompanies": [
|
||||
{
|
||||
"companyId": 24,
|
||||
"companyName": "Allianz SE",
|
||||
"ticker": "ALV",
|
||||
"sector": "Insurance",
|
||||
"alerts": 6,
|
||||
"alertVolume": 1450000.0,
|
||||
"avgRiskScore": 82
|
||||
}
|
||||
],
|
||||
"runbooksExecutedToday": 41
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Transactions
|
||||
|
||||
#### GET /transactions
|
||||
|
||||
Liste alle Transaktionen mit globalen Filtern (Portfolio-weite Transaction Review).
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Typ | Default | Beschreibung |
|
||||
|-----------|-----|---------|--------------|
|
||||
| `search` | string | - | Match gegen Reference, Counterparty, Company |
|
||||
| `status` | enum | `all` | `all`, `true_positive`, `false_positive`, `cleared` |
|
||||
| `page` | integer | `1` | Seiten-Nummer (min: 1) |
|
||||
| `perPage` | integer | `12` | Items pro Seite (min: 1, max: 100) |
|
||||
|
||||
**Request:**
|
||||
```http
|
||||
GET /api/transactions?status=true_positive&page=1&perPage=12 HTTP/1.1
|
||||
Cookie: laravel_session=...
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"filters": {
|
||||
"statusOptions": [
|
||||
{
|
||||
"value": "true_positive",
|
||||
"label": "Bestätigte Treffer"
|
||||
},
|
||||
{
|
||||
"value": "false_positive",
|
||||
"label": "Fehlalarme"
|
||||
},
|
||||
{
|
||||
"value": "cleared",
|
||||
"label": "Freigegeben"
|
||||
}
|
||||
],
|
||||
"perPage": 12
|
||||
},
|
||||
"metrics": {
|
||||
"total": {
|
||||
"count": 312,
|
||||
"amount": 98765432.10
|
||||
},
|
||||
"byStatus": {
|
||||
"true_positive": {
|
||||
"count": 42,
|
||||
"amount": 15200000.0
|
||||
},
|
||||
"false_positive": {
|
||||
"count": 89,
|
||||
"amount": 32100000.0
|
||||
},
|
||||
"cleared": {
|
||||
"count": 181,
|
||||
"amount": 51465432.10
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": [
|
||||
{
|
||||
"id": 512,
|
||||
"company": {
|
||||
"id": 12,
|
||||
"name": "Allianz",
|
||||
"legalName": "Allianz SE",
|
||||
"ticker": "ALV",
|
||||
"sector": "Insurance",
|
||||
"country": "Germany",
|
||||
"headquarters": "Munich",
|
||||
"kycRiskLevel": "high",
|
||||
"summary": "Multinational insurance provider with EMEA focus."
|
||||
},
|
||||
"counterparty": "Alpine Holdings Ltd.",
|
||||
"counterpartyCountry": "Switzerland",
|
||||
"status": "true_positive",
|
||||
"statusLabel": "Bestätigter Treffer",
|
||||
"requiresReview": true,
|
||||
"riskScore": 87,
|
||||
"amount": 245000.75,
|
||||
"currency": "EUR",
|
||||
"reference": "PAY-2024-10-1942",
|
||||
"channel": "SWIFT",
|
||||
"executedAt": "2025-01-18T09:14:00Z",
|
||||
"flaggedReason": "Counterparty on sanctions watchlist"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"perPage": 12,
|
||||
"total": 128,
|
||||
"lastPage": 11
|
||||
},
|
||||
"selectedTransactionId": null,
|
||||
"selectedTransaction": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### GET /transactions/{transactionId}
|
||||
|
||||
Hole detaillierte Transaction Case File.
|
||||
|
||||
**Path Parameters:**
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
|-----------|-----|--------------|
|
||||
| `transactionId` | integer | Transaction ID |
|
||||
|
||||
**Request:**
|
||||
```http
|
||||
GET /api/transactions/512 HTTP/1.1
|
||||
Cookie: laravel_session=...
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"id": 512,
|
||||
"company": { ... },
|
||||
"counterparty": "Alpine Holdings Ltd.",
|
||||
"status": "true_positive",
|
||||
"statusLabel": "Bestätigter Treffer",
|
||||
"requiresReview": true,
|
||||
"riskScore": 87,
|
||||
"amount": 245000.75,
|
||||
"currency": "EUR",
|
||||
"reference": "PAY-2024-10-1942",
|
||||
"channel": "SWIFT",
|
||||
"executedAt": "2025-01-18T09:14:00Z",
|
||||
"flaggedBy": "Screening Engine",
|
||||
"flaggedReason": "Counterparty matched to EU sanctions list",
|
||||
"signals": [
|
||||
{
|
||||
"type": "Adverse Media",
|
||||
"value": "Enforcement action reported in 2024-11",
|
||||
"weight": 0.8
|
||||
},
|
||||
{
|
||||
"type": "Sanctions",
|
||||
"value": "EU Sanctions List Match",
|
||||
"weight": 1.0
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Session ungültig
|
||||
- `404 Not Found` - Transaction existiert nicht
|
||||
|
||||
---
|
||||
|
||||
### 3. Companies
|
||||
|
||||
#### GET /companies/search
|
||||
|
||||
Suche Companies und erhalte Screening-Übersicht.
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Typ | Default | Beschreibung |
|
||||
|-----------|-----|---------|--------------|
|
||||
| `q` | string | - | Freitext-Suche (Name, Legal Name, Ticker, Sector) |
|
||||
| `limit` | integer | `6` | Max. Ergebnisse (min: 1, max: 25) |
|
||||
|
||||
**Request:**
|
||||
```http
|
||||
GET /api/companies/search?q=Allianz&limit=6 HTTP/1.1
|
||||
Cookie: laravel_session=...
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"overview": {
|
||||
"totalCompanies": 40,
|
||||
"openAlerts": 112,
|
||||
"openAlertVolume": 5640000.0,
|
||||
"averageRiskScore": 71,
|
||||
"watchlistHits": 9,
|
||||
"automationShare": 82
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Allianz",
|
||||
"legalName": "Allianz SE",
|
||||
"ticker": "ALV",
|
||||
"sector": "Insurance",
|
||||
"country": "Germany",
|
||||
"headquarters": "Munich",
|
||||
"kycRiskLevel": "high",
|
||||
"summary": "Multinational insurance provider with EMEA focus.",
|
||||
"alertCount": 7,
|
||||
"alertVolume": 980000.0,
|
||||
"alertRiskScore": 79,
|
||||
"latestAlert": {
|
||||
"transactionId": 731,
|
||||
"counterparty": "Baltic Commodities LLC",
|
||||
"executedAt": "2025-01-17T11:48:00Z",
|
||||
"channel": "SWIFT",
|
||||
"flaggedReason": "Pattern matches sanctions typology",
|
||||
"riskScore": 88
|
||||
}
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"query": "Allianz",
|
||||
"resultCount": 6,
|
||||
"limit": 6
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### GET /companies/{companyId}
|
||||
|
||||
Hole Company-Profil.
|
||||
|
||||
**Path Parameters:**
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
|-----------|-----|--------------|
|
||||
| `companyId` | integer | Company ID |
|
||||
|
||||
**Request:**
|
||||
```http
|
||||
GET /api/companies/12 HTTP/1.1
|
||||
Cookie: laravel_session=...
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Allianz",
|
||||
"legalName": "Allianz SE",
|
||||
"ticker": "ALV",
|
||||
"sector": "Insurance",
|
||||
"country": "Germany",
|
||||
"headquarters": "Munich",
|
||||
"kycRiskLevel": "high",
|
||||
"summary": "Multinational insurance provider with EMEA focus.",
|
||||
"createdAt": "2024-10-15T08:30:00Z",
|
||||
"updatedAt": "2025-01-18T14:22:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Session ungültig
|
||||
- `404 Not Found` - Company existiert nicht
|
||||
|
||||
---
|
||||
|
||||
#### GET /companies/{companyId}/transactions
|
||||
|
||||
Liste alle Transactions für eine Company.
|
||||
|
||||
**Path Parameters:**
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
|-----------|-----|--------------|
|
||||
| `companyId` | integer | Company ID |
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Typ | Default | Beschreibung |
|
||||
|-----------|-----|---------|--------------|
|
||||
| `status` | enum | `all` | `all`, `true_positive`, `false_positive`, `cleared` |
|
||||
| `channel` | string | `all` | Channel-Filter (z.B. `SWIFT`, `SEPA`) |
|
||||
| `page` | integer | `1` | Seiten-Nummer |
|
||||
| `perPage` | integer | `10` | Items pro Seite (min: 1, max: 100) |
|
||||
|
||||
**Request:**
|
||||
```http
|
||||
GET /api/companies/12/transactions?status=true_positive&page=1&perPage=10 HTTP/1.1
|
||||
Cookie: laravel_session=...
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"company": {
|
||||
"id": 12,
|
||||
"name": "Allianz",
|
||||
"legalName": "Allianz SE",
|
||||
"ticker": "ALV",
|
||||
"sector": "Insurance",
|
||||
"country": "Germany",
|
||||
"headquarters": "Munich",
|
||||
"kycRiskLevel": "high",
|
||||
"summary": "Multinational insurance provider..."
|
||||
},
|
||||
"filters": {
|
||||
"statusOptions": [
|
||||
{
|
||||
"value": "true_positive",
|
||||
"label": "Bestätigte Treffer"
|
||||
}
|
||||
],
|
||||
"channelOptions": [
|
||||
{
|
||||
"value": "SWIFT",
|
||||
"label": "SWIFT"
|
||||
},
|
||||
{
|
||||
"value": "SEPA",
|
||||
"label": "SEPA"
|
||||
}
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"totalCount": 96,
|
||||
"totalVolume": 7200000.0,
|
||||
"openAlerts": {
|
||||
"count": 12,
|
||||
"amount": 1850000.0
|
||||
},
|
||||
"highRiskShare": 28,
|
||||
"last30Days": {
|
||||
"count": 15,
|
||||
"amount": 980000.0
|
||||
},
|
||||
"byStatus": {
|
||||
"true_positive": {
|
||||
"count": 12,
|
||||
"amount": 1850000.0
|
||||
},
|
||||
"false_positive": {
|
||||
"count": 24,
|
||||
"amount": 2100000.0
|
||||
},
|
||||
"cleared": {
|
||||
"count": 60,
|
||||
"amount": 3250000.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": [
|
||||
{
|
||||
"id": 877,
|
||||
"company": { ... },
|
||||
"counterparty": "Alpine Holdings Ltd.",
|
||||
"status": "true_positive",
|
||||
"riskScore": 87,
|
||||
"amount": 245000.75,
|
||||
"currency": "EUR",
|
||||
"reference": "PAY-2024-10-1942",
|
||||
"channel": "SWIFT",
|
||||
"executedAt": "2025-01-18T09:14:00Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"perPage": 10,
|
||||
"total": 12,
|
||||
"lastPage": 2
|
||||
},
|
||||
"selectedTransactionId": null,
|
||||
"selectedTransaction": null,
|
||||
"recentAlerts": [
|
||||
{
|
||||
"id": 911,
|
||||
"counterparty": "Northbridge Trading Ltd.",
|
||||
"executedAt": "2025-01-18T14:52:00Z",
|
||||
"channel": "SWIFT",
|
||||
"status": "true_positive",
|
||||
"statusLabel": "Bestätigter Treffer",
|
||||
"riskScore": 92
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Session ungültig
|
||||
- `404 Not Found` - Company nicht gefunden oder keine Transactions
|
||||
|
||||
---
|
||||
|
||||
#### GET /companies/{companyId}/transactions/{transactionId}
|
||||
|
||||
Hole Transaction Case File mit Company-Context und History.
|
||||
|
||||
**Path Parameters:**
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
|-----------|-----|--------------|
|
||||
| `companyId` | integer | Company ID |
|
||||
| `transactionId` | integer | Transaction ID |
|
||||
|
||||
**Request:**
|
||||
```http
|
||||
GET /api/companies/12/transactions/877 HTTP/1.1
|
||||
Cookie: laravel_session=...
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"id": 877,
|
||||
"company": { ... },
|
||||
"counterparty": "Alpine Holdings Ltd.",
|
||||
"status": "true_positive",
|
||||
"statusLabel": "Bestätigter Treffer",
|
||||
"requiresReview": true,
|
||||
"riskScore": 87,
|
||||
"amount": 245000.75,
|
||||
"currency": "EUR",
|
||||
"reference": "PAY-2024-10-1942",
|
||||
"channel": "SWIFT",
|
||||
"executedAt": "2025-01-18T09:14:00Z",
|
||||
"flaggedBy": "Screening Engine",
|
||||
"flaggedReason": "Counterparty matched to EU sanctions list",
|
||||
"signals": [
|
||||
{
|
||||
"type": "Adverse Media",
|
||||
"value": "Enforcement action reported in 2024-11",
|
||||
"weight": 0.8
|
||||
}
|
||||
],
|
||||
"recommendedActions": [
|
||||
{
|
||||
"title": "Verdachtsmeldung vorbereiten",
|
||||
"description": "Erstellen Sie den Meldeentwurf für die FIU und sichern Sie Belege."
|
||||
},
|
||||
{
|
||||
"title": "Enhanced Due Diligence",
|
||||
"description": "Prüfen Sie zusätzliche Informationsquellen zur Counterparty."
|
||||
}
|
||||
],
|
||||
"counterpartyHistory": [
|
||||
{
|
||||
"id": 765,
|
||||
"executedAt": "2024-12-22T15:37:00Z",
|
||||
"channel": "SWIFT",
|
||||
"reference": "PAY-2024-12-1187",
|
||||
"amount": 99000.0,
|
||||
"currency": "EUR",
|
||||
"riskScore": 74
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Session ungültig
|
||||
- `404 Not Found` - Transaction nicht gefunden für diese Company
|
||||
|
||||
---
|
||||
|
||||
## Datenmodelle
|
||||
|
||||
### Transaction Status
|
||||
|
||||
```typescript
|
||||
enum TransactionStatus {
|
||||
TRUE_POSITIVE = 'true_positive', // Kritisches Risiko
|
||||
FALSE_POSITIVE = 'false_positive', // Hohes Risiko
|
||||
CLEARED = 'cleared' // Geringes Risiko
|
||||
}
|
||||
```
|
||||
|
||||
### KYC Risk Level
|
||||
|
||||
```typescript
|
||||
enum KycRiskLevel {
|
||||
LOW = 'low',
|
||||
HIGH = 'high',
|
||||
CRITICAL = 'critical'
|
||||
}
|
||||
```
|
||||
|
||||
### Pagination Meta
|
||||
|
||||
```json
|
||||
{
|
||||
"page": 1,
|
||||
"perPage": 12,
|
||||
"total": 128,
|
||||
"lastPage": 11
|
||||
}
|
||||
```
|
||||
|
||||
### Count Amount Summary
|
||||
|
||||
```json
|
||||
{
|
||||
"count": 42,
|
||||
"amount": 2750000.50
|
||||
}
|
||||
```
|
||||
|
||||
### Transaction Signal
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "Adverse Media",
|
||||
"value": "Enforcement action reported in 2024-11",
|
||||
"weight": 0.8
|
||||
}
|
||||
```
|
||||
|
||||
### Recommended Action
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "Verdachtsmeldung vorbereiten",
|
||||
"description": "Erstellen Sie den Meldeentwurf für die FIU..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Beispiele
|
||||
|
||||
### cURL-Beispiele
|
||||
|
||||
#### Login & Session Cookie erhalten
|
||||
|
||||
```bash
|
||||
# Login
|
||||
curl -c cookies.txt -X POST http://trusted_ai.test/login \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-d "email=user@example.com&password=secret"
|
||||
|
||||
# Session Cookie ist jetzt in cookies.txt gespeichert
|
||||
```
|
||||
|
||||
#### Dashboard Overview abrufen
|
||||
|
||||
```bash
|
||||
curl -b cookies.txt http://trusted_ai.test/api/dashboard/overview
|
||||
```
|
||||
|
||||
#### Transactions filtern
|
||||
|
||||
```bash
|
||||
curl -b cookies.txt "http://trusted_ai.test/api/transactions?status=true_positive&page=1&perPage=12"
|
||||
```
|
||||
|
||||
#### Company suchen
|
||||
|
||||
```bash
|
||||
curl -b cookies.txt "http://trusted_ai.test/api/companies/search?q=Allianz&limit=6"
|
||||
```
|
||||
|
||||
#### Company Transactions abrufen
|
||||
|
||||
```bash
|
||||
curl -b cookies.txt "http://trusted_ai.test/api/companies/12/transactions?status=all&page=1"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### JavaScript (Fetch API)
|
||||
|
||||
```javascript
|
||||
// Session Cookie wird automatisch vom Browser gesendet
|
||||
|
||||
// Dashboard Overview
|
||||
const overview = await fetch('/api/dashboard/overview', {
|
||||
credentials: 'include' // Wichtig: Session Cookie mitsenden
|
||||
}).then(r => r.json());
|
||||
|
||||
console.log(overview);
|
||||
|
||||
// Transactions mit Filter
|
||||
const transactions = await fetch('/api/transactions?status=true_positive&page=1&perPage=12', {
|
||||
credentials: 'include'
|
||||
}).then(r => r.json());
|
||||
|
||||
console.log(transactions.data);
|
||||
|
||||
// Company Search
|
||||
const companies = await fetch('/api/companies/search?q=Allianz', {
|
||||
credentials: 'include'
|
||||
}).then(r => r.json());
|
||||
|
||||
console.log(companies.results);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### TypeScript Types
|
||||
|
||||
```typescript
|
||||
// Dashboard Overview Response
|
||||
interface DashboardOverview {
|
||||
generatedAt: string;
|
||||
activeAnalysts: number;
|
||||
totalTransactions: number;
|
||||
totalVolume: number;
|
||||
alertsToday: number;
|
||||
averageAlertsPerAnalyst: number;
|
||||
precisionRate: number;
|
||||
activeAlerts: {
|
||||
count: number;
|
||||
highRiskCount: number;
|
||||
};
|
||||
riskSegments: RiskSegment[];
|
||||
topCompanies: TopCompanyAlert[];
|
||||
runbooksExecutedToday: number;
|
||||
}
|
||||
|
||||
// Transaction Collection Response
|
||||
interface TransactionCollectionResponse {
|
||||
filters: {
|
||||
statusOptions: StatusOption[];
|
||||
perPage: number;
|
||||
};
|
||||
metrics: TransactionMetrics;
|
||||
data: TransactionPreview[];
|
||||
pagination: PaginationMeta;
|
||||
selectedTransactionId: number | null;
|
||||
selectedTransaction: TransactionDetail | null;
|
||||
}
|
||||
|
||||
// Company Search Response
|
||||
interface CompanySearchResponse {
|
||||
overview: CompanySearchOverview;
|
||||
results: CompanySearchResult[];
|
||||
meta: {
|
||||
query: string | null;
|
||||
resultCount: number;
|
||||
limit: number;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Standard Error Response
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Error message",
|
||||
"errors": {
|
||||
"field": ["Validation error"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### HTTP Status Codes
|
||||
|
||||
| Code | Bedeutung | Beschreibung |
|
||||
|------|-----------|--------------|
|
||||
| `200` | OK | Request erfolgreich |
|
||||
| `401` | Unauthorized | Session ungültig oder abgelaufen |
|
||||
| `404` | Not Found | Resource nicht gefunden |
|
||||
| `422` | Unprocessable Entity | Validierungsfehler |
|
||||
| `500` | Internal Server Error | Server-Fehler |
|
||||
|
||||
### Beispiel: 401 Unauthorized
|
||||
|
||||
```json
|
||||
HTTP/1.1 401 Unauthorized
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"message": "Unauthenticated."
|
||||
}
|
||||
```
|
||||
|
||||
**Aktion:** Redirect zu `/login`
|
||||
|
||||
### Beispiel: 404 Not Found
|
||||
|
||||
```json
|
||||
HTTP/1.1 404 Not Found
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"message": "Company not found."
|
||||
}
|
||||
```
|
||||
|
||||
### Beispiel: 422 Validation Error
|
||||
|
||||
```json
|
||||
HTTP/1.1 422 Unprocessable Entity
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"message": "The given data was invalid.",
|
||||
"errors": {
|
||||
"status": ["The selected status is invalid."],
|
||||
"page": ["The page must be at least 1."]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
### Aktueller Status
|
||||
|
||||
**Aktuell:** Kein Rate Limiting implementiert.
|
||||
|
||||
### Geplant (Future)
|
||||
|
||||
```
|
||||
Rate Limit: 60 Requests pro Minute pro User
|
||||
Header: X-RateLimit-Limit, X-RateLimit-Remaining
|
||||
```
|
||||
|
||||
**Response bei Überschreitung:**
|
||||
```json
|
||||
HTTP/1.1 429 Too Many Requests
|
||||
Content-Type: application/json
|
||||
Retry-After: 60
|
||||
|
||||
{
|
||||
"message": "Too many requests. Please try again later."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
### Version 1.0.0 (2025-01-19)
|
||||
|
||||
**Initial Release**
|
||||
|
||||
**Endpoints:**
|
||||
- ✅ `GET /dashboard/overview` - Dashboard KPIs
|
||||
- ✅ `GET /transactions` - Portfolio-wide Transactions
|
||||
- ✅ `GET /transactions/{id}` - Transaction Detail
|
||||
- ✅ `GET /companies/search` - Company Search
|
||||
- ✅ `GET /companies/{id}` - Company Profile
|
||||
- ✅ `GET /companies/{id}/transactions` - Company Transactions
|
||||
- ✅ `GET /companies/{id}/transactions/{id}` - Company Transaction Detail
|
||||
|
||||
**Features:**
|
||||
- Session-basierte Authentifizierung
|
||||
- Pagination Support
|
||||
- Filter & Search
|
||||
- Metrics & Aggregationen
|
||||
- OpenAPI 3.1 Spezifikation
|
||||
|
||||
---
|
||||
|
||||
## Implementierungs-Status
|
||||
|
||||
### ⚠️ Wichtig: API noch nicht implementiert!
|
||||
|
||||
Die in diesem Dokument beschriebenen Endpoints sind **aktuell noch nicht implementiert**.
|
||||
|
||||
**Status:**
|
||||
- ✅ OpenAPI Spezifikation vorhanden ([swagger.yaml](../swagger.yaml))
|
||||
- ❌ API Routes noch nicht definiert (`routes/api.php` ist leer)
|
||||
- ❌ API Controllers noch nicht erstellt
|
||||
- ❌ API Responses noch nicht implementiert
|
||||
|
||||
### Nächste Schritte zur Implementierung
|
||||
|
||||
1. **API Routes definieren:**
|
||||
```php
|
||||
// routes/api.php
|
||||
Route::middleware(['auth:sanctum'])->group(function () {
|
||||
Route::get('/dashboard/overview', [DashboardController::class, 'overview']);
|
||||
Route::get('/transactions', [TransactionController::class, 'index']);
|
||||
Route::get('/transactions/{transaction}', [TransactionController::class, 'show']);
|
||||
Route::get('/companies/search', [CompanyController::class, 'search']);
|
||||
Route::get('/companies/{company}', [CompanyController::class, 'show']);
|
||||
Route::get('/companies/{company}/transactions', [CompanyController::class, 'transactions']);
|
||||
});
|
||||
```
|
||||
|
||||
2. **API Controllers erstellen:**
|
||||
```bash
|
||||
php artisan make:controller Api/DashboardController
|
||||
php artisan make:controller Api/TransactionController
|
||||
php artisan make:controller Api/CompanyController
|
||||
```
|
||||
|
||||
3. **API Resources erstellen:**
|
||||
```bash
|
||||
php artisan make:resource TransactionResource
|
||||
php artisan make:resource CompanyResource
|
||||
```
|
||||
|
||||
4. **Tests schreiben:**
|
||||
```bash
|
||||
php artisan make:test Api/DashboardTest
|
||||
php artisan make:test Api/TransactionTest
|
||||
php artisan make:test Api/CompanyTest
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
### API-Übersicht
|
||||
|
||||
| Kategorie | Endpoints | Status |
|
||||
|-----------|-----------|--------|
|
||||
| Dashboard | 1 | ⚠️ Spezifiziert, nicht implementiert |
|
||||
| Transactions | 2 | ⚠️ Spezifiziert, nicht implementiert |
|
||||
| Companies | 4 | ⚠️ Spezifiziert, nicht implementiert |
|
||||
| **Gesamt** | **7** | - |
|
||||
|
||||
### Datenmodelle
|
||||
|
||||
- **DashboardOverview** - Dashboard-KPIs
|
||||
- **TransactionCollectionResponse** - Paginierte Transactions
|
||||
- **TransactionDetail** - Detaillierte Transaction
|
||||
- **CompanySearchResponse** - Company-Suchergebnisse
|
||||
- **CompanyDetail** - Company-Profil
|
||||
- **CompanyTransactionsResponse** - Company-spezifische Transactions
|
||||
|
||||
### Authentifizierung
|
||||
|
||||
**Session-basiert** via Laravel Session Cookie
|
||||
- Login erforderlich
|
||||
- Cookie-basierte Authentifizierung
|
||||
- CSRF-Protection
|
||||
|
||||
---
|
||||
|
||||
**Erstellt:** 2025-11-24
|
||||
**Version:** 1.0.0
|
||||
**Autor:** Risk Intelligence Platform Team
|
||||
**OpenAPI Spec:** [swagger.yaml](../swagger.yaml)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,991 @@
|
||||
# Entwickler-Setup-Guide: Risk Intelligence Platform
|
||||
|
||||
## 📋 Inhaltsverzeichnis
|
||||
|
||||
1. [Voraussetzungen](#voraussetzungen)
|
||||
2. [Schnellstart](#schnellstart)
|
||||
3. [Detaillierte Installation](#detaillierte-installation)
|
||||
4. [Datenbank-Setup](#datenbank-setup)
|
||||
5. [Environment-Konfiguration](#environment-konfiguration)
|
||||
6. [Frontend-Assets](#frontend-assets)
|
||||
7. [Erste Schritte](#erste-schritte)
|
||||
8. [Development-Workflow](#development-workflow)
|
||||
9. [Troubleshooting](#troubleshooting)
|
||||
10. [Nützliche Commands](#nützliche-commands)
|
||||
|
||||
---
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
### Erforderliche Software
|
||||
|
||||
| Software | Mindestversion | Empfohlen | Installation |
|
||||
|----------|---------------|-----------|--------------|
|
||||
| **PHP** | 8.2 | 8.4.14+ | [Laravel Herd](https://herd.laravel.com) |
|
||||
| **Composer** | 2.0 | Latest | Via Herd oder [getcomposer.org](https://getcomposer.org) |
|
||||
| **Node.js** | 18.x | 20.x+ | [nodejs.org](https://nodejs.org) |
|
||||
| **npm** | 9.x | Latest | Mit Node.js installiert |
|
||||
| **PostgreSQL** | 14.x | 16.x+ | [postgresql.org](https://www.postgresql.org) |
|
||||
| **Git** | 2.x | Latest | [git-scm.com](https://git-scm.com) |
|
||||
|
||||
### Empfohlene Tools
|
||||
|
||||
- **Laravel Herd** - Lokale PHP-Entwicklungsumgebung (macOS)
|
||||
- **TablePlus** / **pgAdmin** - PostgreSQL GUI
|
||||
- **VS Code** - Editor mit PHP/Laravel Extensions
|
||||
- **Postman** / **Insomnia** - API Testing (optional)
|
||||
|
||||
### PHP Extensions
|
||||
|
||||
Folgende PHP Extensions werden benötigt:
|
||||
|
||||
```bash
|
||||
# Prüfe installierte Extensions
|
||||
php -m
|
||||
|
||||
# Benötigte Extensions:
|
||||
- pdo_pgsql # PostgreSQL Driver
|
||||
- mbstring # Multibyte String
|
||||
- xml # XML Support
|
||||
- curl # HTTP Client
|
||||
- bcmath # Precision Math
|
||||
- fileinfo # File Information
|
||||
- json # JSON Support
|
||||
- openssl # Encryption
|
||||
- tokenizer # PHP Tokenizer
|
||||
- zip # ZIP Archive
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Schnellstart
|
||||
|
||||
Für erfahrene Entwickler - vollständige Installation in 5 Minuten:
|
||||
|
||||
```bash
|
||||
# 1. Repository klonen
|
||||
git clone <repository-url> risk-platform
|
||||
cd risk-platform
|
||||
|
||||
# 2. Dependencies installieren & Setup ausführen
|
||||
composer setup
|
||||
|
||||
# 3. PostgreSQL-Datenbank erstellen (siehe unten)
|
||||
# Anpassen: .env mit DB-Credentials
|
||||
|
||||
# 4. Migrations ausführen
|
||||
php artisan migrate --seed
|
||||
|
||||
# 5. Development-Server starten
|
||||
composer run dev
|
||||
```
|
||||
|
||||
**Fertig!** Die Applikation läuft auf [http://localhost:8000](http://localhost:8000)
|
||||
|
||||
---
|
||||
|
||||
## Detaillierte Installation
|
||||
|
||||
### Schritt 1: Repository klonen
|
||||
|
||||
```bash
|
||||
# Via HTTPS
|
||||
git clone https://github.com/your-org/risk-platform.git
|
||||
cd risk-platform
|
||||
|
||||
# Oder via SSH
|
||||
git clone git@github.com:your-org/risk-platform.git
|
||||
cd risk-platform
|
||||
```
|
||||
|
||||
### Schritt 2: PHP Dependencies installieren
|
||||
|
||||
```bash
|
||||
composer install
|
||||
```
|
||||
|
||||
**Was passiert dabei?**
|
||||
- Installiert alle Laravel-Pakete
|
||||
- Installiert Livewire, Flux UI, Fortify
|
||||
- Installiert Dev-Dependencies (Pest, Pint, Boost)
|
||||
- Generiert Autoload-Files
|
||||
|
||||
### Schritt 3: Environment-Datei erstellen
|
||||
|
||||
```bash
|
||||
# .env.example nach .env kopieren
|
||||
cp .env.example .env
|
||||
|
||||
# Application Key generieren
|
||||
php artisan key:generate
|
||||
```
|
||||
|
||||
### Schritt 4: Node Dependencies installieren
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
**Was passiert dabei?**
|
||||
- Installiert Vite
|
||||
- Installiert Tailwind CSS v4
|
||||
- Installiert Build-Tools
|
||||
|
||||
---
|
||||
|
||||
## Datenbank-Setup
|
||||
|
||||
### PostgreSQL Installation
|
||||
|
||||
#### macOS (mit Homebrew)
|
||||
|
||||
```bash
|
||||
# PostgreSQL installieren
|
||||
brew install postgresql@16
|
||||
|
||||
# Als Service starten
|
||||
brew services start postgresql@16
|
||||
|
||||
# Verbindung testen
|
||||
psql postgres
|
||||
```
|
||||
|
||||
#### macOS (mit Postgres.app)
|
||||
|
||||
1. Download von [postgresapp.com](https://postgresapp.com)
|
||||
2. App starten
|
||||
3. Default Server initialisieren
|
||||
|
||||
#### Ubuntu/Debian
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install postgresql postgresql-contrib
|
||||
sudo systemctl start postgresql
|
||||
sudo systemctl enable postgresql
|
||||
```
|
||||
|
||||
### Datenbank erstellen
|
||||
|
||||
```bash
|
||||
# Als postgres User einloggen
|
||||
psql postgres
|
||||
|
||||
# Oder direkt mit spezifischem User
|
||||
sudo -u postgres psql
|
||||
```
|
||||
|
||||
```sql
|
||||
-- Datenbank erstellen
|
||||
CREATE DATABASE risk_platform_db;
|
||||
|
||||
-- User erstellen (optional)
|
||||
CREATE USER risk_user WITH ENCRYPTED PASSWORD 'your_secure_password';
|
||||
|
||||
-- Rechte vergeben
|
||||
GRANT ALL PRIVILEGES ON DATABASE risk_platform_db TO risk_user;
|
||||
|
||||
-- In PostgreSQL 15+ auch Schema-Rechte vergeben
|
||||
\c risk_platform_db
|
||||
GRANT ALL ON SCHEMA public TO risk_user;
|
||||
|
||||
-- Exit
|
||||
\q
|
||||
```
|
||||
|
||||
### Schemas erstellen
|
||||
|
||||
```sql
|
||||
-- Verbindung zur DB
|
||||
psql -U risk_user -d risk_platform_db
|
||||
|
||||
-- PUBLIC Schema (wird automatisch erstellt)
|
||||
-- BACKEND Schema erstellen
|
||||
CREATE SCHEMA IF NOT EXISTS backend;
|
||||
|
||||
-- Rechte für BACKEND Schema
|
||||
GRANT ALL ON SCHEMA backend TO risk_user;
|
||||
|
||||
-- Exit
|
||||
\q
|
||||
```
|
||||
|
||||
### Verbindung testen
|
||||
|
||||
```bash
|
||||
# Direkter Connect
|
||||
psql -h 127.0.0.1 -p 5432 -U risk_user -d risk_platform_db
|
||||
|
||||
# Mit Laravel Tinker
|
||||
php artisan tinker
|
||||
>>> DB::connection('pgsql_second')->select('SELECT version()');
|
||||
>>> DB::connection('backend')->select('SELECT current_schema()');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Environment-Konfiguration
|
||||
|
||||
### .env Datei anpassen
|
||||
|
||||
```bash
|
||||
# .env öffnen und anpassen
|
||||
nano .env
|
||||
```
|
||||
|
||||
#### Grundkonfiguration
|
||||
|
||||
```ini
|
||||
APP_NAME="Risk Intelligence Platform"
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:xxx # Wird von key:generate erstellt
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost:8000
|
||||
|
||||
APP_LOCALE=de
|
||||
APP_FALLBACK_LOCALE=en
|
||||
APP_FAKER_LOCALE=de_DE
|
||||
```
|
||||
|
||||
#### Datenbank-Konfiguration (Wichtig!)
|
||||
|
||||
```ini
|
||||
# Default Connection (PUBLIC Schema)
|
||||
DB_CONNECTION=pgsql
|
||||
DB_CONNECTION2=pgsql
|
||||
DB_HOST2=127.0.0.1
|
||||
DB_PORT2=5432
|
||||
DB_DATABASE2=risk_platform_db
|
||||
DB_USERNAME2=risk_user
|
||||
DB_PASSWORD2=your_secure_password
|
||||
```
|
||||
|
||||
**Wichtig:** Die Applikation nutzt `DB_*2` Variablen für PostgreSQL!
|
||||
|
||||
#### Cache & Session
|
||||
|
||||
```ini
|
||||
CACHE_STORE=database
|
||||
SESSION_DRIVER=database
|
||||
QUEUE_CONNECTION=database
|
||||
```
|
||||
|
||||
**Warum database?**
|
||||
- Einfaches Setup ohne Redis
|
||||
- Funktioniert out-of-the-box
|
||||
- Für Produktion: Wechsel zu Redis empfohlen
|
||||
|
||||
#### Mail-Konfiguration (Development)
|
||||
|
||||
```ini
|
||||
MAIL_MAILER=log
|
||||
MAIL_FROM_ADDRESS="noreply@risk-platform.test"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
```
|
||||
|
||||
Mails werden in `storage/logs/laravel.log` gespeichert.
|
||||
|
||||
#### Optional: Redis (für bessere Performance)
|
||||
|
||||
```ini
|
||||
CACHE_STORE=redis
|
||||
SESSION_DRIVER=redis
|
||||
QUEUE_CONNECTION=redis
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
```
|
||||
|
||||
### Vollständige .env Vorlage
|
||||
|
||||
<details>
|
||||
<summary>Klicken für vollständige .env Beispiel-Datei</summary>
|
||||
|
||||
```ini
|
||||
APP_NAME="Risk Intelligence Platform"
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:xxx
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost:8000
|
||||
|
||||
APP_LOCALE=de
|
||||
APP_FALLBACK_LOCALE=en
|
||||
APP_FAKER_LOCALE=de_DE
|
||||
|
||||
APP_MAINTENANCE_DRIVER=file
|
||||
PHP_CLI_SERVER_WORKERS=4
|
||||
BCRYPT_ROUNDS=12
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_STACK=single
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=debug
|
||||
|
||||
# PostgreSQL Configuration
|
||||
DB_CONNECTION=pgsql
|
||||
DB_CONNECTION2=pgsql
|
||||
DB_HOST2=127.0.0.1
|
||||
DB_PORT2=5432
|
||||
DB_DATABASE2=risk_platform_db
|
||||
DB_USERNAME2=risk_user
|
||||
DB_PASSWORD2=your_secure_password
|
||||
|
||||
# Session & Cache
|
||||
SESSION_DRIVER=database
|
||||
SESSION_LIFETIME=120
|
||||
SESSION_ENCRYPT=false
|
||||
SESSION_PATH=/
|
||||
SESSION_DOMAIN=null
|
||||
|
||||
CACHE_STORE=database
|
||||
QUEUE_CONNECTION=database
|
||||
|
||||
# Broadcasting & Filesystem
|
||||
BROADCAST_CONNECTION=log
|
||||
FILESYSTEM_DISK=local
|
||||
|
||||
# Mail
|
||||
MAIL_MAILER=log
|
||||
MAIL_FROM_ADDRESS="noreply@risk-platform.test"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
# Vite
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
```
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## Frontend-Assets
|
||||
|
||||
### Assets kompilieren
|
||||
|
||||
```bash
|
||||
# Development Build (einmalig)
|
||||
npm run build
|
||||
|
||||
# Development mit Hot Reload
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Was macht `npm run dev`?
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ VITE v7.0.4 ready in X ms │
|
||||
│ │
|
||||
│ ➜ Local: http://localhost:5173/ │
|
||||
│ ➜ Network: use --host to expose │
|
||||
│ │
|
||||
│ ➜ Laravel: http://localhost:8000 │
|
||||
└─────────────────────────────────────────────────┘
|
||||
|
||||
✓ compiled successfully
|
||||
```
|
||||
|
||||
- Startet Vite Dev-Server auf Port 5173
|
||||
- Hot Module Replacement (HMR) aktiviert
|
||||
- Tailwind CSS v4 wird kompiliert
|
||||
- Livewire-Assets werden gebundled
|
||||
|
||||
### Production Build
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
|
||||
# Output:
|
||||
# dist/assets/app-xxxxx.js
|
||||
# dist/assets/app-xxxxx.css
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Erste Schritte
|
||||
|
||||
### 1. Migrations ausführen
|
||||
|
||||
```bash
|
||||
# Alle Migrations ausführen
|
||||
php artisan migrate
|
||||
|
||||
# Mit Seeding (Test-Daten)
|
||||
php artisan migrate --seed
|
||||
|
||||
# Migration-Status prüfen
|
||||
php artisan migrate:status
|
||||
```
|
||||
|
||||
**Erwartete Tabellen nach Migration:**
|
||||
|
||||
```
|
||||
┌──────────────────────────────────┬────────┐
|
||||
│ Migration │ Ran? │
|
||||
├──────────────────────────────────┼────────┤
|
||||
│ 0001_01_01_000000_create_users │ Yes │
|
||||
│ 0001_01_01_000001_create_cache │ Yes │
|
||||
│ 0001_01_01_000002_create_jobs │ Yes │
|
||||
│ 2025_09_02_075243_add_two_factor │ Yes │
|
||||
│ 2025_10_20_181750_create_companies │ Yes │
|
||||
│ 2025_10_20_181753_create_transactions │ Yes │
|
||||
│ 2025_11_16_140224_add_output_columns │ Yes │
|
||||
│ 2025_11_16_150000_create_backend_data_pool │ Yes │
|
||||
│ ... │ │
|
||||
└──────────────────────────────────┴────────┘
|
||||
```
|
||||
|
||||
### 2. Test-User erstellen
|
||||
|
||||
```bash
|
||||
php artisan tinker
|
||||
```
|
||||
|
||||
```php
|
||||
// Test-User erstellen
|
||||
$user = App\Models\User::create([
|
||||
'name' => 'Admin User',
|
||||
'email' => 'admin@example.com',
|
||||
'password' => bcrypt('password'),
|
||||
'email_verified_at' => now(),
|
||||
]);
|
||||
|
||||
// Oder mit Factory
|
||||
App\Models\User::factory()->create([
|
||||
'email' => 'test@example.com',
|
||||
]);
|
||||
|
||||
exit
|
||||
```
|
||||
|
||||
### 3. Development-Server starten
|
||||
|
||||
#### Option A: Composer Dev Command (Empfohlen)
|
||||
|
||||
```bash
|
||||
composer run dev
|
||||
```
|
||||
|
||||
**Startet parallel:**
|
||||
- `php artisan serve` → http://localhost:8000
|
||||
- `php artisan queue:listen` → Queue Worker
|
||||
- `php artisan pail` → Live Logs
|
||||
- `npm run dev` → Vite Dev Server
|
||||
|
||||
#### Option B: Einzelne Services manuell
|
||||
|
||||
```bash
|
||||
# Terminal 1: Laravel Server
|
||||
php artisan serve
|
||||
|
||||
# Terminal 2: Vite Dev Server
|
||||
npm run dev
|
||||
|
||||
# Terminal 3 (optional): Queue Worker
|
||||
php artisan queue:work
|
||||
|
||||
# Terminal 4 (optional): Logs
|
||||
php artisan pail
|
||||
```
|
||||
|
||||
#### Option C: Laravel Herd (macOS)
|
||||
|
||||
Wenn du Laravel Herd nutzt:
|
||||
|
||||
1. Projekt in Herd-Verzeichnis verschieben
|
||||
2. Automatische Domain: `risk-platform.test`
|
||||
3. HTTPS automatisch aktiviert
|
||||
4. Kein `php artisan serve` notwendig
|
||||
|
||||
```bash
|
||||
# In Herd-Verzeichnis verschieben
|
||||
mv ~/risk-platform ~/Herd/risk-platform
|
||||
|
||||
# Browser öffnen
|
||||
open https://risk-platform.test
|
||||
```
|
||||
|
||||
### 4. Applikation öffnen
|
||||
|
||||
Browser öffnen: [http://localhost:8000](http://localhost:8000)
|
||||
|
||||
**Login-Credentials:**
|
||||
- Email: `test@example.com`
|
||||
- Password: `password`
|
||||
|
||||
---
|
||||
|
||||
## Development-Workflow
|
||||
|
||||
### Typischer Entwicklungstag
|
||||
|
||||
```bash
|
||||
# 1. Morgen: Repository aktualisieren
|
||||
git pull origin main
|
||||
|
||||
# 2. Dependencies aktualisieren (falls composer.lock geändert)
|
||||
composer install
|
||||
npm install
|
||||
|
||||
# 3. Neue Migrations (falls vorhanden)
|
||||
php artisan migrate
|
||||
|
||||
# 4. Dev-Server starten
|
||||
composer run dev
|
||||
|
||||
# 5. Am Ende: Code formatieren
|
||||
vendor/bin/pint
|
||||
|
||||
# 6. Tests ausführen
|
||||
php artisan test
|
||||
|
||||
# 7. Commit & Push
|
||||
git add .
|
||||
git commit -m "feat: neue feature"
|
||||
git push
|
||||
```
|
||||
|
||||
### Code-Formatierung
|
||||
|
||||
```bash
|
||||
# Alle Dateien formatieren
|
||||
vendor/bin/pint
|
||||
|
||||
# Nur geänderte Dateien
|
||||
vendor/bin/pint --dirty
|
||||
|
||||
# Test-Modus (ohne Änderungen)
|
||||
vendor/bin/pint --test
|
||||
```
|
||||
|
||||
### Tests ausführen
|
||||
|
||||
```bash
|
||||
# Alle Tests
|
||||
php artisan test
|
||||
|
||||
# Nur Feature Tests
|
||||
php artisan test --testsuite=Feature
|
||||
|
||||
# Nur Unit Tests
|
||||
php artisan test --testsuite=Unit
|
||||
|
||||
# Spezifische Test-Datei
|
||||
php artisan test tests/Feature/CompanyTest.php
|
||||
|
||||
# Mit Filter
|
||||
php artisan test --filter=testCompanyCreation
|
||||
|
||||
# Mit Coverage (benötigt Xdebug)
|
||||
php artisan test --coverage
|
||||
```
|
||||
|
||||
### Backend-Daten synchronisieren
|
||||
|
||||
```bash
|
||||
# Stats anzeigen (kein Sync)
|
||||
php artisan backend:sync-data-pool --stats
|
||||
|
||||
# Incremental Sync
|
||||
php artisan backend:sync-data-pool --incremental
|
||||
|
||||
# Full Sync
|
||||
php artisan backend:sync-data-pool --full
|
||||
|
||||
# Transformation
|
||||
php artisan backend:transform-data-pool
|
||||
|
||||
# Kompletter Rebuild
|
||||
php artisan backend:rebuild
|
||||
```
|
||||
|
||||
### Scheduler lokal testen
|
||||
|
||||
```bash
|
||||
# Schedule Worker (läuft dauerhaft)
|
||||
php artisan schedule:work
|
||||
|
||||
# Oder: Nächste Due-Tasks anzeigen
|
||||
php artisan schedule:list
|
||||
|
||||
# Einzelnen Task testen
|
||||
php artisan schedule:test sync-backend-data-pool-incremental
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Problem: "SQLSTATE[08006] Connection refused"
|
||||
|
||||
**Ursache:** PostgreSQL läuft nicht oder falsche Credentials
|
||||
|
||||
**Lösung:**
|
||||
```bash
|
||||
# PostgreSQL-Status prüfen
|
||||
brew services list | grep postgresql
|
||||
|
||||
# PostgreSQL starten
|
||||
brew services start postgresql@16
|
||||
|
||||
# Verbindung testen
|
||||
psql -h 127.0.0.1 -p 5432 -U risk_user -d risk_platform_db
|
||||
|
||||
# .env prüfen
|
||||
cat .env | grep DB_
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Problem: "Class 'PDO' not found"
|
||||
|
||||
**Ursache:** PHP PostgreSQL Extension fehlt
|
||||
|
||||
**Lösung:**
|
||||
```bash
|
||||
# Installierte Extensions prüfen
|
||||
php -m | grep pdo
|
||||
|
||||
# Mit Herd (macOS)
|
||||
# Extensions sind normalerweise vorinstalliert
|
||||
|
||||
# Oder PHP neu installieren via Homebrew
|
||||
brew reinstall php@8.4
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Problem: "Vite manifest not found"
|
||||
|
||||
**Ursache:** Frontend-Assets nicht kompiliert
|
||||
|
||||
**Lösung:**
|
||||
```bash
|
||||
# Development Build
|
||||
npm run build
|
||||
|
||||
# Oder Dev-Server starten
|
||||
npm run dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Problem: "419 Page Expired" bei Forms
|
||||
|
||||
**Ursache:** CSRF-Token ungültig (Session abgelaufen)
|
||||
|
||||
**Lösung:**
|
||||
```bash
|
||||
# Cache leeren
|
||||
php artisan config:clear
|
||||
php artisan cache:clear
|
||||
php artisan view:clear
|
||||
|
||||
# Browser: Hard Refresh (Cmd+Shift+R / Ctrl+Shift+R)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Problem: Migrations laufen nicht
|
||||
|
||||
**Ursache:** Datenbank-Schema fehlt oder keine Rechte
|
||||
|
||||
**Lösung:**
|
||||
```bash
|
||||
# Schema-Rechte prüfen
|
||||
psql -U risk_user -d risk_platform_db
|
||||
|
||||
# In psql:
|
||||
SELECT schema_name FROM information_schema.schemata;
|
||||
|
||||
# Rechte vergeben
|
||||
GRANT ALL ON SCHEMA public TO risk_user;
|
||||
GRANT ALL ON ALL TABLES IN SCHEMA public TO risk_user;
|
||||
|
||||
# Migration erneut versuchen
|
||||
php artisan migrate
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Problem: Queue-Jobs laufen nicht
|
||||
|
||||
**Ursache:** Queue-Worker läuft nicht
|
||||
|
||||
**Lösung:**
|
||||
```bash
|
||||
# Queue-Worker starten
|
||||
php artisan queue:work
|
||||
|
||||
# Oder mit Auto-Restart bei Code-Änderungen
|
||||
php artisan queue:listen
|
||||
|
||||
# Failed Jobs anzeigen
|
||||
php artisan queue:failed
|
||||
|
||||
# Failed Jobs erneut versuchen
|
||||
php artisan queue:retry all
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Problem: "Class not found" Fehler
|
||||
|
||||
**Ursache:** Autoload-Cache veraltet
|
||||
|
||||
**Lösung:**
|
||||
```bash
|
||||
# Autoload neu generieren
|
||||
composer dump-autoload
|
||||
|
||||
# Alle Caches leeren
|
||||
php artisan optimize:clear
|
||||
|
||||
# Oder einzeln:
|
||||
php artisan config:clear
|
||||
php artisan cache:clear
|
||||
php artisan route:clear
|
||||
php artisan view:clear
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Problem: Livewire-Components laden nicht
|
||||
|
||||
**Ursache:** Volt-Components nicht registriert
|
||||
|
||||
**Lösung:**
|
||||
```bash
|
||||
# Volt Provider prüfen
|
||||
cat bootstrap/providers.php | grep Volt
|
||||
|
||||
# Cache leeren
|
||||
php artisan optimize:clear
|
||||
|
||||
# Browser Cache leeren
|
||||
# Cmd+Shift+R (macOS) oder Ctrl+Shift+R (Windows/Linux)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Problem: Styling fehlt / Tailwind funktioniert nicht
|
||||
|
||||
**Ursache:** Vite-Server läuft nicht oder falsche Konfiguration
|
||||
|
||||
**Lösung:**
|
||||
```bash
|
||||
# Vite Dev-Server neu starten
|
||||
npm run dev
|
||||
|
||||
# Oder Production-Build
|
||||
npm run build
|
||||
|
||||
# Tailwind-Config prüfen
|
||||
cat tailwind.config.js
|
||||
|
||||
# Node-Modules neu installieren
|
||||
rm -rf node_modules package-lock.json
|
||||
npm install
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nützliche Commands
|
||||
|
||||
### Laravel Artisan
|
||||
|
||||
```bash
|
||||
# Liste aller Commands
|
||||
php artisan list
|
||||
|
||||
# Command-Hilfe
|
||||
php artisan help migrate
|
||||
|
||||
# Interaktive Shell
|
||||
php artisan tinker
|
||||
|
||||
# Cache Management
|
||||
php artisan cache:clear
|
||||
php artisan config:clear
|
||||
php artisan route:clear
|
||||
php artisan view:clear
|
||||
php artisan optimize:clear # Alle Caches auf einmal
|
||||
|
||||
# Database
|
||||
php artisan db:show # DB-Info anzeigen
|
||||
php artisan migrate:status # Migration-Status
|
||||
php artisan migrate:fresh --seed # DB neu aufsetzen + Seeds
|
||||
|
||||
# Make Commands
|
||||
php artisan make:model Company
|
||||
php artisan make:controller CompanyController
|
||||
php artisan make:migration create_companies_table
|
||||
php artisan make:livewire CompanySearch
|
||||
php artisan make:test CompanyTest
|
||||
php artisan make:class Services/MyService
|
||||
|
||||
# Routes
|
||||
php artisan route:list # Alle Routes anzeigen
|
||||
php artisan route:list --path=companies # Gefiltert
|
||||
```
|
||||
|
||||
### Composer
|
||||
|
||||
```bash
|
||||
# Dependencies installieren
|
||||
composer install
|
||||
|
||||
# Development-Dependencies überspringen
|
||||
composer install --no-dev
|
||||
|
||||
# Einzelnes Package installieren
|
||||
composer require laravel/telescope
|
||||
|
||||
# Package entfernen
|
||||
composer remove laravel/telescope
|
||||
|
||||
# Autoload regenerieren
|
||||
composer dump-autoload
|
||||
|
||||
# Setup ausführen (custom script)
|
||||
composer setup
|
||||
|
||||
# Dev-Server starten (custom script)
|
||||
composer run dev
|
||||
|
||||
# Tests ausführen (custom script)
|
||||
composer test
|
||||
```
|
||||
|
||||
### NPM
|
||||
|
||||
```bash
|
||||
# Dependencies installieren
|
||||
npm install
|
||||
|
||||
# Dev-Server starten
|
||||
npm run dev
|
||||
|
||||
# Production Build
|
||||
npm run build
|
||||
|
||||
# Package installieren
|
||||
npm install alpine.js
|
||||
|
||||
# Package entfernen
|
||||
npm uninstall alpine.js
|
||||
|
||||
# Outdated Packages prüfen
|
||||
npm outdated
|
||||
|
||||
# Updates installieren
|
||||
npm update
|
||||
```
|
||||
|
||||
### Git
|
||||
|
||||
```bash
|
||||
# Aktueller Branch
|
||||
git branch
|
||||
|
||||
# Neuen Branch erstellen
|
||||
git checkout -b feature/neue-funktion
|
||||
|
||||
# Änderungen anzeigen
|
||||
git status
|
||||
git diff
|
||||
|
||||
# Commit
|
||||
git add .
|
||||
git commit -m "feat: neue funktion"
|
||||
git push origin feature/neue-funktion
|
||||
|
||||
# Main aktualisieren
|
||||
git checkout main
|
||||
git pull origin main
|
||||
```
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
```bash
|
||||
# Verbinden
|
||||
psql -U risk_user -d risk_platform_db
|
||||
|
||||
# In psql:
|
||||
\dt # Alle Tabellen
|
||||
\d companies # Tabellen-Schema anzeigen
|
||||
\dn # Alle Schemas
|
||||
\du # Alle User
|
||||
\l # Alle Datenbanken
|
||||
\q # Exit
|
||||
|
||||
# Backup erstellen
|
||||
pg_dump -U risk_user risk_platform_db > backup.sql
|
||||
|
||||
# Backup einspielen
|
||||
psql -U risk_user risk_platform_db < backup.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nächste Schritte
|
||||
|
||||
Nach erfolgreichem Setup:
|
||||
|
||||
1. **Architektur-Dokumentation lesen** → [docs/architecture-overview.md](architecture-overview.md)
|
||||
2. **Backend-Sync Commands kennenlernen** → [docs/backend-sync-commands.md](backend-sync-commands.md)
|
||||
3. **Code-Konventionen studieren** → [CLAUDE.md](../CLAUDE.md)
|
||||
4. **Tests schreiben & ausführen** → `php artisan test`
|
||||
5. **Erste Änderungen committen** → `git commit`
|
||||
|
||||
---
|
||||
|
||||
## Hilfe & Support
|
||||
|
||||
### Dokumentation
|
||||
|
||||
- **Architektur-Übersicht:** [docs/architecture-overview.md](architecture-overview.md)
|
||||
- **Backend-Sync:** [docs/backend-sync-commands.md](backend-sync-commands.md)
|
||||
- **Scheduling:** [docs/scheduling-setup.md](scheduling-setup.md)
|
||||
- **Migration:** [docs/sync-migration-instructions.md](sync-migration-instructions.md)
|
||||
|
||||
### Laravel Dokumentation
|
||||
|
||||
- **Laravel 12:** [https://laravel.com/docs/12.x](https://laravel.com/docs/12.x)
|
||||
- **Livewire 3:** [https://livewire.laravel.com](https://livewire.laravel.com)
|
||||
- **Flux UI:** [https://flux.laravel.com](https://flux.laravel.com)
|
||||
- **Pest Testing:** [https://pestphp.com](https://pestphp.com)
|
||||
|
||||
### Logs prüfen
|
||||
|
||||
```bash
|
||||
# Application Logs (Live)
|
||||
tail -f storage/logs/laravel.log
|
||||
|
||||
# Nur Fehler
|
||||
tail -f storage/logs/laravel.log | grep ERROR
|
||||
|
||||
# Mit Laravel Pail (farbig)
|
||||
php artisan pail
|
||||
```
|
||||
|
||||
### Debugging
|
||||
|
||||
```bash
|
||||
# Laravel Debugbar (installiert)
|
||||
# Aktiviert automatisch wenn APP_DEBUG=true
|
||||
# Erscheint am unteren Bildschirmrand im Browser
|
||||
|
||||
# Tinker für schnelle Tests
|
||||
php artisan tinker
|
||||
>>> App\Models\Company::count()
|
||||
>>> DB::table('transactions')->latest()->first()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Setup-Zeit:** ~15-30 Minuten
|
||||
**Erstellt:** 2025-11-24
|
||||
**Version:** 1.0
|
||||
**Autor:** Risk Intelligence Platform Team
|
||||
|
||||
Viel Erfolg beim Entwickeln! 🚀
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user