fix(alerts): add AGENT_LIFECYCLE to condition_kind_enum + readable error toasts
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 2m5s
CI / docker (push) Successful in 1m19s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 37s

Backend
 - V18 migration adds AGENT_LIFECYCLE to condition_kind_enum. Java
   ConditionKind enum shipped with this value but no Postgres migration
   extended the type, so any AGENT_LIFECYCLE rule insert failed with
   "invalid input value for enum condition_kind_enum".
 - ALTER TYPE ... ADD VALUE lives alone in its migration per Postgres
   constraint that the new value cannot be referenced in the same tx.
 - V18MigrationIT asserts the enum now contains all 7 kinds.

Frontend
 - Add describeApiError(e) helper to unwrap openapi-fetch error bodies
   (Spring error JSON) into readable strings. String(e) on a plain
   object rendered "[object Object]" in toasts — the actual failure
   reason was hidden from the user.
 - Replace String(e) in all 13 toast descriptions across the alerting
   and outbound-connection mutation paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-21 20:23:14 +02:00
parent 181a479037
commit b7d201d743
13 changed files with 81 additions and 17 deletions

24
ui/src/api/errors.ts Normal file
View File

@@ -0,0 +1,24 @@
/**
* Turn whatever a fetch/mutation threw into a user-readable string.
*
* openapi-fetch rethrows the parsed response body as-is (a plain object like
* `{ error, message, path, status, timestamp }` for Spring errors), so
* `String(e)` renders "[object Object]" in a toast. This helper prefers an
* Error.message, falls back to a `message` field on plain objects, then
* Spring's `error` field, and finally JSON-stringifies the rest.
*/
export function describeApiError(e: unknown): string {
if (e instanceof Error) return e.message;
if (typeof e === 'string') return e;
if (typeof e === 'object' && e !== null) {
const obj = e as Record<string, unknown>;
if (typeof obj.message === 'string' && obj.message) return obj.message;
if (typeof obj.error === 'string' && obj.error) return obj.error;
try {
return JSON.stringify(e);
} catch {
return String(e);
}
}
return String(e);
}