Files
gala-ki-spielwiese/agent-backend/CLAUDE.md

146 lines
4.9 KiB
Markdown
Raw Normal View History

# CLAUDE.md — Dateieingang Service
## Projektbeschreibung
Quarkus-Backend-Service, der einen n8n-Workflow bei Galabau ersetzt.
Empfängt einen HTTP-Trigger von der APEX Automation, holt ZIP-Dateien von einem SFTP-Server,
entpackt sie, lädt die Dateien in OCI Object Storage hoch und benachrichtigt die Oracle-Datenbank
via ORDS.
## Dokumentation
Nur bei Bedarf lesen — nicht automatisch in den Kontext laden:
| Dokument | Inhalt |
|---|---|
| `SETUP.md` | Installation (WSL, Java 25, Quarkus CLI), Build, Dev-Server, Umgebungsvariablen |
| `docs/Architecture.md` | Pipeline-Steps, Service-Mapping, Konfigurationsstruktur |
| `docs/Logging.md` | Logging-Stack (LGTM), MDC-Felder, Log-Events pro Step |
| `docs/Plan.md` | Vollständiger Architektur- und Migrationsplan |
| `docs/SFTP-Integration.md` | SSHJ-Architektur, Host-Key-Verification, Fehlerbehandlung |
Datenbankspezifische Dokumente: `../database/`
## Tech-Stack
| Komponente | Technologie |
|---|---|
| Framework | Quarkus (Java 25) |
| Build | Maven (Maven Wrapper `./mvnw`) |
| SFTP | SSHJ (`com.hierynomus:sshj`) |
| ZIP-Verarbeitung | Apache Commons Compress |
| OCI Object Storage | OCI Java SDK (`oci-java-sdk-objectstorage`) |
| ORDS-Client | MicroProfile REST Client |
| Fehlertoleranz | SmallRye Fault Tolerance (`@Retry`, `@Timeout`) |
| Async | Quarkus Managed Executor (`quarkus-smallrye-context-propagation`) |
| Logging | Quarkus + OTLP → Loki/Grafana (Dev: `quarkus-observability-devservices-lgtm`) |
| JSON | Jackson |
## Paketstruktur
```
src/main/java/de/galabau/dateieingang/
├── api/ # REST Endpoint (eingehend von APEX Automation)
├── sftp/ # SSHJ: list, download, rename
├── zip/ # ZIP-Entpacken (Apache Commons Compress)
├── oci/ # OCI Object Storage Upload + Marker
├── ords/ # Oracle ORDS REST-Client (process_incoming)
├── pipeline/ # Orchestrierung des Gesamtworkflows
├── model/ # ProcessingContext, FileEntry, DTOs
├── config/ # @ConfigMapping Interfaces
└── exception/ # Domain-Exceptions
```
## Externe Abhängigkeiten
| Service | Konfiguration | Zweck |
|---|---|---|
| SFTP-Server | `galabau.sftp.*` | ZIP-Dateien abholen |
| OCI Object Storage | `galabau.oci.*` | Dateien + Marker ablegen |
| Oracle ORDS | `galabau.ords.*` | DB-Verarbeitung auslösen |
| APEX Automation | ruft `/api/process-incoming` auf | Trigger (stündlich) |
## Konventionen
- **Sprache**: Dokumentation auf Deutsch, Code auf Englisch
- **Konfiguration**: Alle URLs, Ports, Benutzernamen in `application.properties`; Passwörter und Keys via `${ENV_VAR}` aus Umgebungsvariablen
- **Kein eigenes Scheduling**: Trigger kommt von APEX Automation via HTTP POST
- **Async**: Pipeline läuft im Hintergrund, APEX bekommt sofort 202 Accepted
- **Cleanup**: Lokale Arbeitsdateien immer im `finally`-Block löschen
- **Einzelinstanz**: Kein Clustering — `AtomicBoolean`-Guard verhindert gleichzeitige Läufe
## Java Code Guidelines
### Sprache
Dokumentation und Kommentare auf Deutsch, Code (Klassen-, Methoden-, Variablennamen) auf Englisch.
### Javadoc
Javadoc für alle öffentlichen Methoden der Service-Klassen und alle Klassen in `model/`.
Nicht nötig für triviale Getter, Test-Methoden oder selbsterklärende Signaturen.
```java
// ✅ Javadoc sinnvoll
/**
* Lädt alle Dateien aus dem ProcessingContext in OCI Object Storage hoch
* und schreibt danach den Marker für die DB-Verarbeitung.
*
* @param context enthält die Liste der hochzuladenden Dateien und den Ziel-Prefix
* @throws OciException bei persistenten OCI-Fehlern (4xx)
*/
public void upload(ProcessingContext context) throws OciException { ... }
```
### Exceptions
Eigene Domain-Exceptions pro Integrationsbereich. Möglichst nicht `Exception` oder `RuntimeException` fangen.
```java
// ✅
throw new SftpException("SFTP rename failed for: " + filename, cause);
// ❌
throw new RuntimeException("something went wrong");
```
### Logging
`io.quarkus.logging.Log` — statische API, kein Field-Boilerplate.
```java
import io.quarkus.logging.Log;
@ApplicationScoped
public class SftpService {
public List<String> listZipFiles() throws SftpException {
Log.infof("Listing ZIP files on SFTP: %s", config.remotePath());
Log.errorf(e, "SFTP list failed on %s", config.host());
}
}
```
Immer mit MDC-Kontext loggen (wird automatisch angehängt, siehe `docs/Logging.md`).
Nie sensible Daten loggen (Passwörter, Keys, Key-Dateipfade).
### Konfiguration
Keine hardcodierten Werte — alles via `@ConfigMapping`.
```java
// ✅
@ConfigMapping(prefix = "galabau.sftp")
public interface SftpConfig { ... }
// ❌
private static final String HOST = "sftp.lieferant.de";
```
### CDI / Services
Services als `@ApplicationScoped`. Keine manuelle Instanziierung mit `new`.
### Paketgrenzen
Kein direkter Zugriff auf interne Klassen fremder Pakete — nur über die öffentliche Service-API.