Introduces ApiError class in client.ts that parses Spring Boot error
bodies to extract human-readable messages (message, error, detail fields).
Adds errorMessage() helper used by all toast descriptions instead of
raw String(err) which dumped JSON blobs to the user.
Affected: all 10 page components that display error toasts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix vertical alignment of Lucide icons inside Button children across
all pages by adding verticalAlign offsets (-3px for 16px icons, -2px
for 14px icons). The design system Button wraps children in an inline
span, so SVG icons defaulted to baseline alignment.
Hide the redundant top-right "Create Tenant" button on VendorTenantsPage
when no tenants exist — the EmptyState already provides that action.
Add icons to all vendor sidebar sub-items for consistency (previously
only Email Connector had one).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace inline FileField and native <input type="file"> with
FileInput from @cameleer/design-system (drag-and-drop, icons, clear)
- Update CertificatesPage and SsoPage to use FileInput + FormField
- Fix /certs volume permissions (chmod 775) so cameleer user can write
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Encrypted PKCS#8 private keys are decrypted during staging using the
provided password. The decrypted key is stored for Traefik (which needs
cleartext PEM). Unencrypted keys continue to work without a password.
- CertificateManager.stage() accepts optional keyPassword
- DockerCertificateManager handles EncryptedPrivateKeyInfo decryption
- UI: password field in upload form (vendor CertificatesPage)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Truncate fingerprint with hover tooltip
- Remove duplicate warning icon in stale banner
- Style file inputs to match design system
- Bump grid min-width for better card spacing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>