Spring Security was blocking /v3/api-docs with 401, preventing
npm run generate:api from fetching the spec. The springdoc paths are
now whitelisted only when the dev Spring profile is active.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All server-side fetch calls now go through createApiClient() from
$lib/api.server.ts, which wraps openapi-fetch with the generated OpenAPI
types. This means backend changes are reflected in the frontend after
running npm run generate:api.
- Add stub src/lib/generated/api.ts (replaced by generate:api output)
- Fix GroupController: missing /api prefix and ResponseStatusException
- Root, conversations, persons, documents pages all use typed client
- Error handling uses apiError.code directly (no parseBackendError needed)
- Edit page load uses typed client; PUT action keeps raw fetch (multipart)
- Login keeps raw fetch (explicit Authorization header, not cookie auth)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend now returns { code: ErrorCode, message: string } for all errors,
making it language-agnostic. Frontend maps codes to localised strings via
Paraglide (en/de/es), so translations live in messages/*.json.
- Add ErrorCode enum and DomainException with static factory methods
- Update GlobalExceptionHandler to return ErrorResponse(code, message)
- Replace ResponseStatusException throughout controllers/services/aspects
- Add frontend errors.ts with parseBackendError() and getErrorMessage()
- getErrorMessage() delegates to Paraglide m.error_*() functions
- Add error_* keys to messages/en.json, de.json, es.json
- Update all page.server.ts files to use the new error utilities
- Fix hardcoded localhost URLs in admin and login pages
- Fix missing baseUrl in deleteTag action
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The async import previously ran fire-and-forget with no way to know
if it succeeded, failed, or was still running.
- Add ImportStatus record (state, message, processed count, startedAt)
and a volatile currentStatus field updated throughout the async run
- POST /api/admin/trigger-import now returns 202 Accepted with initial status
- GET /api/admin/import-status lets callers poll for the current state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three related issues:
- READ_ALL was stored in the DB but missing from the Permission enum
- ADMIN_USER, ADMIN_TAG and ADMIN_PERMISSION were in the enum and used
in controllers but never granted to any user, making those endpoints
permanently inaccessible
- No runtime signal when a DB permission string drifts from the enum
Changes:
- Add READ_ALL to Permission enum
- Grant all six permissions to the Administrators group in DataInitializer
- Warn in CustomUserDetailsService when a DB permission string has no
matching Permission enum value
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Spring Session was pulled in as a dependency but never used — auth is
stateless HTTP Basic, so sessions are never written. Removed:
- spring-boot-starter-session-jdbc (and test variant) from pom.xml
- spring_session and spring_session_attributes tables/indexes/constraints
from V1__initial_schema.sql
Added V2 migration to drop the tables on existing databases that already
ran V1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous comment implied CSRF was disabled as a temporary dev
convenience. Replaced it with an explanation of why it is safe with
the current Authorization-header-based auth scheme, and added a
clear note on when it must be re-enabled.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
initData was creating an 'Admins' group with identical permissions to
the 'Administrators' group already created by initAdminUser, resulting
in two redundant groups on every fresh start. Removed the duplicate,
dropped the now-unused groupRepo parameter, and corrected the log
message which claimed 50 persons were created when only 4 were.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace application.properties with application.yaml (base/prod config)
and application-dev.yaml (dev overrides: show-sql=true)
- Add Maven 'dev' profile (activeByDefault) and 'prod' profile to pom.xml;
spring-boot:run picks up the active Spring profile automatically
- Guard DataInitializer.initData with @Profile("dev") so test data is
never seeded in production
Local dev: ./mvnw spring-boot:run (dev profile active by default)
Production: SPRING_PROFILES_ACTIVE env var controls the Spring profile;
Maven profiles are irrelevant for the packaged JAR.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The log statement revealed the default admin password in application
logs. Now only the username is logged, using the resolved variable
instead of a hardcoded string.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Missing closing braces caused Spring to inject the literal placeholder
string instead of resolving the property, silently ignoring any
app.admin.username / app.admin.password env-var overrides.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>