ad81a7c93e
assertNoRecentDuplicateDocument warf einen generischen Error → die Catch-Blöcke in den drei ContractDocument-Schreibpfaden mappten das auf 500, obwohl es klar eine 400-Class-Situation (Caller-Fehler: Duplikat-Submit) ist. Neuer ApiError-Helper in utils/apiError: - ApiError(statusCode, message) – einfache Subklasse von Error mit explizitem HTTP-Status. assertNoRecentDuplicateDocument wirft jetzt ApiError(400, ...). Catch-Blöcke gehärtet (Service-Pattern: `error instanceof ApiError ? error.statusCode : <default>`): - contract.controller uploadContractDocument: 400-Default bleibt, ApiError wird honoriert; bonus: multer-Datei wird bei Reject jetzt gelöscht (war vorher orphaned bei Lock-Reject). - cachedEmail.controller saveEmailAsContractDocument: 500-Default, ApiError → 400. - cachedEmail.controller saveAttachmentAsContractDocument: dito. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
19 lines
709 B
TypeScript
19 lines
709 B
TypeScript
/**
|
|
* Erlaubt Service-/Helper-Funktionen, einen Fehler mit explizitem HTTP-
|
|
* Status nach oben zu reichen. Controller können in ihrem `catch` per
|
|
* `instanceof ApiError` den Status auslesen statt pauschal 500 zu liefern.
|
|
*
|
|
* Pentest 64.1 (LOW, 2026-06-02): Race-Lock (assertNoRecentDuplicate-
|
|
* Document) warf einen generischen Error → catch hat 500 zurückgegeben,
|
|
* obwohl die Fehlermeldung "Dokument vor wenigen Sekunden bereits
|
|
* angelegt" eindeutig eine 400-Class-Situation ist.
|
|
*/
|
|
export class ApiError extends Error {
|
|
readonly statusCode: number;
|
|
constructor(statusCode: number, message: string) {
|
|
super(message);
|
|
this.name = 'ApiError';
|
|
this.statusCode = statusCode;
|
|
}
|
|
}
|