fix spelling in migration todo doc

This commit is contained in:
Anthony Stirling
2026-08-04 09:54:32 +01:00
parent 12b55c2771
commit 74bcd5570d
+360 -360
View File
@@ -127,303 +127,303 @@ springdoc did not document. **No operation loses a parameter outright.**
## Deferred behaviour
374 notes were removed from the source and recorded here. These are places that compile
but where the behaviour is a stub, a fallback, or a Spring feature that was dropped rather than
374 notes were removed from the source and recorded here. These are places that compile but
where the behaviour is a stub, a fallback, or a Spring feature that was dropped rather than
ported - so they will not show up in a build and need reading before anyone trusts the
corresponding feature. Grouped by concern.
<details><summary><b>Spring MVC handler registry has no Quarkus equivalent</b> (8)</summary>
- `app/common/src/main/java/stirling/software/common/config/swagger/ToolIOOperationCustomizer.java:38` - GlobalOpenApiCustomizer}, which received the {@code HandlerMethod} for each operation and could read {@code @ToolIO} straight off it. A MicroProfile {@link OASFilter} sees only the document, so the declarations are looked up by path through {@link ToolIORegistry}. That registry is only populated once the container is up, hence {@code RUNTIME_STARTUP} - the schema exported at build time by {@code quarkus.smallrye-openapi.store-schema-directory} therefore carries no {@code x-stirling-io}. TODO:...
- `app/core/src/main/java/stirling/software/SPDF/config/EndpointInspector.java:32` - TODO: Migration required - this previously used Spring MVC's RequestMappingHandlerMapping (org.springframework.web.servlet.mvc.method.*) to enumerate all registered GET handler mappings via the ApplicationContext at ContextRefreshedEvent. Quarkus/JAX-RS (RESTEasy Reactive) has no equivalent runtime-queryable handler-mapping registry. Options for porting: - Build-time scan of @jakarta.ws.rs.Path + @jakarta.ws.rs.GET via a Quarkus build step / Jandex index, or - Query the OpenAPI model (quarkus...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/catalog/McpToolCatalog.java:85` - TODO: Migration required - endpoint discovery relied on Spring MVC's RequestMappingHandlerMapping (ApplicationContext.getBeansOfType(...) -> mapping.getHandlerMethods()) to enumerate every @RequestMapping/@PostMapping handler, its URL patterns (RequestMappingInfo#getDirectPaths), its HTTP methods (RequestMethod POST/PUT), and the HandlerMethod/MethodParameter reflection used to build request schemas. Quarkus/RESTEasy Reactive has no equivalent runtime registry of JAX-RS resources. To restore ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/catalog/McpToolCatalog.java:113` - TODO: Migration required - request body type was previously resolved from Spring's HandlerMethod#getMethodParameters(); resolve the first complex parameter type via plain reflection on the JAX-RS resource method instead, then call schemaGenerator.toSchema(...).
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/catalog/OperationMeta.java:16` - TODO: Migration required - was org.springframework.web.method.HandlerMethod (Spring MVC, no Quarkus equivalent). Replaced with the underlying java.lang.reflect.Method. The collaborator McpToolCatalog must be updated to discover JAX-RS resource methods (e.g. via RESTEasy Reactive ResourceScanningSupport / jakarta.ws.rs annotations) instead of Spring's RequestMappingHandlerMapping, and pass a reflect.Method here.
- `app/proprietary/src/main/java/stirling/software/proprietary/service/AiEngineEndpointResolver.java:44` - TODO: Migration required - this previously enumerated all registered request mappings via Spring MVC's RequestMappingHandlerMapping (org.springframework.web.servlet.mvc.method.*) obtained from the ApplicationContext at ContextRefreshedEvent, keeping every pattern that started with "/api/v1/". Quarkus / JAX-RS (RESTEasy Reactive) has no equivalent runtime-queryable handler-mapping registry. Options for porting: - Build-time scan of @jakarta.ws.rs.Path methods via a Quarkus build step / Jandex ...
- `app/saas/src/main/java/stirling/software/saas/payg/entitlement/EntitlementGuard.java:366` - TODO: Migration required - resolves the resource {@link Method} the original code read from Spring's {@code HandlerMethod}. Until wired to JAX-RS {@code ResourceInfo}, supports a handler that is already a {@link Method} or exposes a no-arg {@code getMethod()} returning one.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:563` - TODO: Migration required - resolves the resource {@link Method} the original code read from Spring's {@code HandlerMethod} (via {@code hm.getMethod()}). Until wired to JAX-RS {@code ResourceInfo}, supports a handler that is already a {@link Method} or exposes a no-arg {@code getMethod()} returning one, preserving the {@code @AutoJobPostMapping} gating.
- `app/common/src/main/java/stirling/software/common/config/swagger/ToolIOOperationCustomizer.java:38` - GlobalOpenApiCustomizer}, which received the {@code HandlerMethod} for each operation and could read {@code @ToolIO} straight off it. A MicroProfile {@link OASFilter} sees only the document, so the declarations are looked up by path through {@link ToolIORegistry}. That registry is only populated once the container is up, hence {@code RUNTIME_STARTUP} - the schema exported at build time by {@code quarkus.smallrye-openapi.store-schema-directory} therefore ...
- `app/core/src/main/java/stirling/software/SPDF/config/EndpointInspector.java:32` - this previously used Spring MVC's RequestMappingHandlerMapping (org.springframework.web.servlet.mvc.method.*) to enumerate all registered GET handler mappings via the ApplicationContext at ContextRefreshedEvent. Quarkus/JAX-RS (RESTEasy Reactive) has no equivalent runtime-queryable handler-mapping registry. Options for porting: - Build-time scan of @jakarta.ws.rs.Path + @jakarta.ws.rs.GET via a Quarkus build step / Jandex index ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/catalog/McpToolCatalog.java:85` - endpoint discovery relied on Spring MVC's RequestMappingHandlerMapping (ApplicationContext.getBeansOfType(...) -> mapping.getHandlerMethods()) to enumerate every @RequestMapping/@PostMapping handler, its URL patterns (RequestMappingInfo#getDirectPaths), its HTTP methods (RequestMethod POST/PUT), and the HandlerMethod/MethodParameter reflection used to build request schemas. Quarkus/RESTEasy Reactive has no equivalent runtime ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/catalog/McpToolCatalog.java:113` - request body type was previously resolved from Spring's HandlerMethod#getMethodParameters(); resolve the first complex parameter type via plain reflection on the JAX-RS resource method instead, then call schemaGenerator.toSchema(...).
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/catalog/OperationMeta.java:16` - was org.springframework.web.method.HandlerMethod (Spring MVC, no Quarkus equivalent). Replaced with the underlying java.lang.reflect.Method. The collaborator McpToolCatalog must be updated to discover JAX-RS resource methods (e.g. via RESTEasy Reactive ResourceScanningSupport / jakarta.ws.rs annotations) instead of Spring's RequestMappingHandlerMapping, and pass a reflect.Method here.
- `app/proprietary/src/main/java/stirling/software/proprietary/service/AiEngineEndpointResolver.java:44` - this previously enumerated all registered request mappings via Spring MVC's RequestMappingHandlerMapping (org.springframework.web.servlet.mvc.method.*) obtained from the ApplicationContext at ContextRefreshedEvent, keeping every pattern that started with "/api/v1/". Quarkus / JAX-RS (RESTEasy Reactive) has no equivalent runtime-queryable handler-mapping registry. Options for porting: - Build-time scan of @jakarta.ws.rs.Path ...
- `app/saas/src/main/java/stirling/software/saas/payg/entitlement/EntitlementGuard.java:366` - resolves the resource {@link Method} the original code read from Spring's {@code HandlerMethod}. Until wired to JAX-RS {@code ResourceInfo}, supports a handler that is already a {@link Method} or exposes a no-arg {@code getMethod()} returning one.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:563` - resolves the resource {@link Method} the original code read from Spring's {@code HandlerMethod} (via {@code hm.getMethod()}). Until wired to JAX-RS {@code ResourceInfo}, supports a handler that is already a {@link Method} or exposes a no-arg {@code getMethod()} returning one, preserving the {@code @AutoJobPostMapping} gating.
</details>
<details><summary><b>Servlet filters / interceptors -> JAX-RS providers</b> (108)</summary>
- `app/common/build.gradle:11` - Servlet bridge: large amounts of controller/filter code use jakarta.servlet (HttpServletRequest, Filter, etc.). quarkus-undertow provides a servlet container on Quarkus so that API resolves and runs. TODO: Migration required - longer term, port servlet usage to JAX-RS (ContainerRequestContext) and drop quarkus-undertow.
- `app/common/build.gradle:27` - REMOVED: spring-boot-starter-aspectj. Quarkus has no AspectJ weaving; quarkus-arc provides CDI interceptors (@AroundInvoke / interceptor bindings) instead. TODO: Migration required - any @Aspect/@Around advice must be rewritten as CDI interceptors.
- `app/core/src/main/java/stirling/software/SPDF/config/LocaleConfiguration.java:11` - TODO: Migration required - this class was a Spring MVC WebMvcConfigurer. Quarkus/JAX-RS has no WebMvcConfigurer, InterceptorRegistry, LocaleChangeInterceptor or SessionLocaleResolver. The locale-resolution logic (computing the default Locale from configuration) is preserved below as a CDI-produced Locale. The two pieces of behavior that previously came from the MVC machinery still need to be wired up by collaborators: 1. The "lang" request-param locale switching (old LocaleChangeInterceptor) ...
- `app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java:38` - are read automatically, so this class is now an {@link OASFilter} (registered via {@code mp.openapi.filter} in application.properties) that reproduces the old programmatic customizations: <ul> <li>API {@link Info} (title, version, license, contact, terms of service, description); <li>the global "AI" {@link Tag}; <li>the {@link Server} entry (optionally from {@code SWAGGER_SERVER_URL}); <li>the {@code ErrorResponse} component schema; <li>the {@code apiKey} security scheme + requirement when lo...
- `app/core/src/main/java/stirling/software/SPDF/config/SpringDocConfig.java:3` - TODO: Migration required - springdoc's GroupedOpenApi (multiple OpenAPI documents grouped by path-matching) has NO direct equivalent in quarkus-smallrye-openapi, which serves a single document built automatically from @Tag/@Operation/JAX-RS annotations. The three groups below (file-processing "/api/v1/**" minus management/system paths, management "/api/v1/admin/**" etc., and system "/api/v1/ui-data/**" etc.) plus the pdfFileOneOfCustomizer (@Qualifier("pdfFileOneOfCustomizer") OpenApiCustomiz...
- `app/core/src/main/java/stirling/software/SPDF/config/WAUTrackingFilter.java:21` - TODO: Migration required - Spring @ConditionalOnProperty(name="security.enableLogin", havingValue="false") had no direct CDI equivalent for conditional bean registration. The filter is now always registered (@Provider) and the condition is enforced at request time by reading the 'security.enableLogin' config property below. Verify the property key matches Quarkus config (originally bound from ApplicationProperties.security.enableLogin).
- `app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java:63` - TODO: Migration required - in Spring, addResourceHandlers also registered the physical resource locations (InstallationPathConfig.getStaticPath() + "classpath:/static/") and an EncodedResourceResolver (gzip/brotli pre-compressed asset serving). In Quarkus, static file serving is handled by quarkus.http via configuration: quarkus.http.static-resources... and/or a Servlet/RouteFilter mapping InstallationPathConfig.getStaticPath() as an external static root. The EncodedResourceResolver behavior ...
- `app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java:152` - TODO: Migration required - Quarkus has built-in CORS handling via quarkus.http.cors.* config properties (quarkus.http.cors.origins, .methods, .headers, .exposed-headers, .access-control-allow-credentials, .access-control-max-age). However, the original logic is *dynamic* (Tauri-mode detection + ApplicationProperties-driven origins + always-on Tauri origins), which static config cannot express. The logic is preserved below and applied via this response filter. Note: a ContainerResponseFilter c...
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:106` - TODO: Migration required - the per-request locale used to come from Spring's LocaleContextHolder (populated by the MVC LocaleChangeInterceptor). Until the equivalent ContainerRequestFilter described in LocaleConfiguration is in place, fall back to the JVM default locale. Localized messages are read from the shared messages.properties bundle (the same bundle ExceptionUtils uses) instead of a Spring MessageSource bean, which no longer exists under Quarkus.
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:806` - TODO: Migration required - the original Spring handler checked HttpServletResponse.isCommitted() and returned null to let Spring write nothing when the response was already committed (e.g. during streaming). JAX-RS ExceptionMapper has no direct access to commit state; returning a Response here is the closest equivalent. If streaming endpoints need the old "do nothing when committed" behavior, a collaborator should detect that condition (e.g. via a ContainerResponseFilter) and short-circuit.
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:873` - TODO: Migration required - locale is the JVM default until the per-request locale ContainerRequestFilter described in LocaleConfiguration replaces Spring's LocaleContextHolder.getLocale().
- `app/core/src/main/resources/application.properties:46` - TODO: Migration required - no direct Quarkus equivalent for the following; handle in code: - spring.threads.virtual.enabled=true -> annotate blocking endpoints with @RunOnVirtualThread - spring.mvc.async.request-timeout -> per-endpoint timeout handling - spring.security.filter.dispatcher-types=REQUEST,ERROR - spring.web.resources.mime-mappings.webmanifest=application/manifest+json - server.servlet.session.tracking-modes=cookie (configure on quarkus-undertow)
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:34` - {@code @Around("@annotation(...Audited)")} advice. Reworked into a CDI {@link Interceptor} bound by the {@code @Audited} annotation; {@code @Around}/{@code ProceedingJoinPoint} became {@code @AroundInvoke}/{@link InvocationContext}. Spring's {@code @Order(10)} (lower precedence, runs after {@code AutoJobAspect}) maps to {@code @Priority}: {@code AutoJobAspect} uses {@code @Priority(20)}, so this audit interceptor uses {@code @Priority(10)} which runs FIRST and populates MDC before the job int...
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:41` - stirling.software.proprietary.audit.Audited}) must be made a CDI {@code @jakarta.interceptor.InterceptorBinding} (and its members marked {@code @jakarta.enterprise.util.Nonbinding}) for this {@code @Interceptor} to bind to it; see the already-migrated {@code AutoJobPostMapping}. That is a separate file and is intentionally left untouched here. TODO: Migration required - {@code AuditService}'s helper methods ({@code createBaseAuditData}, {@code addFileData}, {@code addMethodArguments}, {@code ...
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/ControllerAuditAspect.java:38` - multiple {@code @Around} advices whose pointcuts matched <em>any</em> method annotated with Spring's {@code @GetMapping}/{@code @PostMapping}/{@code @PutMapping}/{@code @DeleteMapping}/ {@code @PatchMapping}/{@code @AutoJobPostMapping}, plus an {@code execution(...)} expression on Spring's {@code ResourceHttpRequestHandler}. {@code @Around}/{@code ProceedingJoinPoint} + {@code MethodSignature} became {@code @AroundInvoke}/{@link InvocationContext}, and {@code RequestContextHolder}/{@code Serv...
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/ControllerAuditAspect.java:204` - TODO: Migration required (collaborator) - AuditService.createBaseAuditData/addFileData/ addMethodArguments/resolveEventType still take org.aspectj.lang.ProceedingJoinPoint (AuditService is not yet migrated). Once AuditService is converted, change those signatures to accept jakarta.interceptor.InvocationContext (getMethod/getParameters/ getTarget cover the data used). These calls pass the InvocationContext and will only typecheck after that collaborator change. Use auditService to create the b...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpApiKeyAuthFilter.java:42` - TODO: Migration required - Spring Security removed. This filter previously read the current Authentication from SecurityContextHolder to decide whether to process the API key. Quarkus has no SecurityContextHolder; the current identity is exposed via io.quarkus.security.identity.SecurityIdentity. With the binding below not yet wired, we always attempt to validate the presented key so the lookup logic is preserved.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpApiKeyAuthFilter.java:51` - TODO: Migration required - bind the resolved user + MCP_SCOPES to the request identity. Spring's UsernamePasswordAuthenticationToken / SecurityContextHolder.setContext(...) has no servlet-filter equivalent in Quarkus. Implement an io.quarkus.security.identity.SecurityIdentityAugmentor (or a custom io.quarkus.vertx.http.runtime.security.HttpAuthenticationMechanism / IdentityProvider keyed off the X-API-KEY / Bearer credential) that produces a SecurityIdentity with principal=user.getUsername() ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpAudienceValidator.java:14` - RFC 8707 audience binding: a JWT at the MCP endpoint must list this server's resource id (or one of the explicitly accepted additional audiences) in its {@code aud} claim. The additional list exists for IdPs that cannot mint resource-specific audiences - e.g. Supabase's OAuth server always issues {@code aud=authenticated}. Fails closed when nothing is configured. TODO: Migration required - this was a Spring Security {@code OAuth2TokenValidator<Jwt>}. Quarkus-oidc has no equivalent validator S...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpAuthenticationEntryPoint.java:17` - Emits 401 + {@code WWW-Authenticate: Bearer resource_metadata="..."} (RFC 9728) from X-Forwarded-* headers. A rejected token also logs the reason and echoes it as {@code error_description}. TODO: Migration required - this was a Spring Security {@code AuthenticationEntryPoint} (commence(...) invoked by the SecurityFilterChain on authentication failure). Quarkus has no SecurityFilterChain equivalent. The 401 response must instead be produced by a Quarkus auth mechanism / failure handler (e.g. a...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpRequestSizeFilter.java:27` - TODO: Migration required - this filter was a Spring OncePerRequestFilter; under Quarkus (quarkus-undertow) register it as a jakarta.servlet.Filter via @WebFilter or a programmatic FilterRegistrationBean equivalent, and ensure it runs once per request and before the MCP endpoint. Registration ordering must be verified by the collaborator wiring the servlet filters.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpSecurityConfig.java:15` - MCP security chain: validates JWTs (JWKS + RFC 8707 audience), maps scope claims to authorities, and fails closed when the issuer is unset. TODO: Migration required - this class was a Spring Security {@code SecurityFilterChain} / {@code HttpSecurity} DSL configuration, which has NO direct Quarkus equivalent. The Spring security DSL has been removed; the equivalent behaviour must be rebuilt on Quarkus primitives: <ul> <li>HTTP path matching ({@code /mcp}, {@code /mcp/**}, {@code /.well-known/o...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpSecurityConfig.java:57` - TODO: Migration required - @Order(Ordered.HIGHEST_PRECEDENCE) and @ConditionalOnProperty(name = "mcp.enabled", havingValue = "true") were removed. Gate MCP security wiring on the runtime property mcp.enabled=true (a runtime toggle, not a build profile, so prefer a runtime guard in the new ContainerRequestFilter/augmentor). Filter ordering (highest precedence) must be re-expressed via JAX-RS @Priority or quarkus.http.auth.permission ordering.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpSecurityConfig.java:66` - TODO: Migration required - UserService was injected @Lazy to break a circular wiring with the security chain. With the Spring chain removed, inject it directly into the new API-key / user-binding ContainerRequestFilters instead of holding it here.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpUserBindingFilter.java:26` - Binds an MCP-validated JWT to a provisioned Stirling user: optionally rejects subjects with no enabled account, then rebinds the principal to the canonical Stirling username (scope authorities only) so audit/metering attribute correctly. TODO: Migration required - this was a Spring Security {@code OncePerRequestFilter} that read and rewrote the {@code SecurityContextHolder} ({@code JwtAuthenticationToken}/{@code Jwt}). Quarkus has no global mutable security context; the canonical replacement ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpUserBindingFilter.java:60` - TODO: Migration required - extract the validated JWT and its claims from the Quarkus SecurityIdentity / JsonWebToken instead of Spring's SecurityContextHolder. The block below preserves the original binding logic but cannot run until that wiring exists, so for now every request passes through untouched.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpUserBindingFilter.java:66` - TODO: Migration required - read the claim value from the validated token, e.g. jsonWebToken.getClaim(usernameClaim). Placeholder keeps the surrounding logic intact.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpUserBindingFilter.java:98` - TODO: Migration required - rebind to the Stirling username, carrying only the OAuth scope authorities. With quarkus-oidc/smallrye-jwt this is done by a SecurityIdentityAugmentor that returns a new SecurityIdentity whose principal name is boundUsername and whose roles are the original token scopes. boundUsername is computed above and ready to feed into that augmentor.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpUserBindingFilter.java:116` - TODO: Migration required - on the Quarkus path, rejection should clear/deny the SecurityIdentity (augmentor throws AuthenticationFailedException) or the ContainerRequestFilter should abortWith(Response.status(403)...). The 403 JSON body below is preserved as the intended response shape.
- `app/proprietary/src/main/java/stirling/software/proprietary/repository/PersistentAuditEventRepository.java:333` - --------------------------------------------------------------------- Multi-value queries for filtering by multiple types and/or principals TODO: Migration required - callers must adapt to the PanacheQuery return type (see class doc). ---------------------------------------------------------------------
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:21` - TODO: Migration required - this class extended Spring Security's SimpleUrlAuthenticationFailureHandler and was wired into the form-login SecurityFilterChain. Quarkus has no direct equivalent for an AuthenticationFailureHandler. The login-failure flow (lockout, bad credentials, oauth2 errors, disabled users) must be re-hosted on a Quarkus authentication mechanism - typically a custom form-auth (quarkus.http.auth.*) or quarkus-oidc - with the redirect decisions implemented in a jakarta.ws.rs.co...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java:24` - TODO: Migration required - this class previously extended Spring Security's SavedRequestAwareAuthenticationSuccessHandler, which is part of the Spring Security form-login filter chain (RedirectStrategy + SavedRequest from the HttpSession). Quarkus has no direct equivalent: post-login redirects are handled by quarkus-oidc / form-auth (quarkus.http.auth.form.landing-page, .location-cookie) or by a custom jakarta.servlet.Filter / ContainerRequestFilter / HttpAuthenticationMechanism. The business...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java:89` - TODO: Migration required - "SPRING_SECURITY_SAVED_REQUEST" was populated by the Spring Security RequestCache. Without the Spring filter chain this attribute is never set, so this branch always falls through to the home-page redirect. The original-destination redirect must be reimplemented via the Quarkus form-auth location cookie or a custom request cache.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/JwtAuthenticationEntryPoint.java:9` - TODO: Migration required - this was a Spring Security AuthenticationEntryPoint (org.springframework.security.web.AuthenticationEntryPoint). Quarkus has no direct AuthenticationEntryPoint SPI; unauthenticated-access handling is wired via quarkus.http.auth.* policies and an AuthenticationFailedException mapper / a jakarta.ws.rs.ext.ExceptionMapper<io.quarkus.security.UnauthorizedException> (or a ContainerRequestFilter). The response-shaping logic below is preserved as a plain helper bean; the c...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/config/EnterpriseEndpointAspect.java:23` - MIGRATION (Spring AOP -> CDI interceptor): was an {@code @Aspect} {@code @Component} with {@code @Around} advice matching {@code @annotation(EnterpriseEndpoint)} / {@code @within(EnterpriseEndpoint)}. Reworked into a CDI {@link Interceptor} bound by the {@code @EnterpriseEndpoint} annotation (pattern: common/aop/AutoJobAspect). {@code @Around} + {@code ProceedingJoinPoint} became {@code @AroundInvoke} + {@link InvocationContext}; {@code joinPoint.proceed()} -> {@code ctx.proceed()}. The Sprin...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/config/PremiumEndpointAspect.java:20` - MIGRATION (Spring AOP -> CDI interceptor): was an {@code @Aspect} with {@code @Around} advice on the {@code @PremiumEndpoint} pointcut ({@code @annotation || @within}). Reworked into a CDI {@link Interceptor} bound by the {@code @PremiumEndpoint} {@code @InterceptorBinding}; {@code @Around}/{@code ProceedingJoinPoint} became {@code @AroundInvoke}/{@link InvocationContext}. The Spring {@code ResponseStatusException(HttpStatus.FORBIDDEN, ...)} became a JAX-RS {@link WebApplicationException} wit...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ProprietaryWebMvcConfig.java:10` - TODO: Migration required - Spring MVC's WebMvcConfigurer / InterceptorRegistry has no Quarkus (JAX-RS / RESTEasy Reactive) equivalent, so this registration class cannot be ported directly.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ProprietaryWebMvcConfig.java:30` - TODO: Migration required - the interceptor registration below was removed: registry.addInterceptor(participantRateLimitInterceptor) .addPathPatterns("/api/v1/workflow/participant/**"); Re-implement as a JAX-RS ContainerRequestFilter bound to that path (see class javadoc).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:31` - Security configuration migrated from a Spring {@code @Configuration}/{@code @EnableWebSecurity} class to a Quarkus CDI bean. TODO: Migration required - This class was built entirely around the Spring Security {@code HttpSecurity} DSL and {@code SecurityFilterChain} beans, which have NO direct Quarkus equivalent. The HTTP security model must be re-expressed declaratively/imperatively: <ul> <li><b>HTTP path policies / authorization</b> (the {@code authorizeHttpRequests} rules: permit static res...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:95` - reusable, non-Spring helper logic (CORS values, X-Frame-Options decision, firewall char patterns, filter/repository factories) is retained as plain methods/producers below. TODO: Migration required - this bean was {@code @DependsOn("runningProOrHigher")} and {@code @Profile("!saas")}. The dependency ordering is approximated by injecting the {@code runningProOrHigher} flag; the {@code !saas} profile gate maps to a Quarkus build profile - use {@code @io.quarkus.arc.profile.UnlessBuildProfile("s...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:176` - Reusable CORS settings preserved from the original {@code corsConfigurationSource()} bean. TODO: Migration required - the Spring {@code CorsConfigurationSource}/ {@code UrlBasedCorsConfigurationSource} types are removed. Apply these values via {@code quarkus.http.cors.*} in {@code application.properties} (origins, methods, headers, exposed-headers, access-control-allow-credentials=true, access-control-max-age=PT1H) or a {@code ContainerResponseFilter}. The origin resolution from {@code applic...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:230` - Resolves the desired X-Frame-Options header value, preserving the original decision logic. TODO: Migration required - apply the returned value via a response filter or {@code quarkus.http.header} config (Spring's {@code HeadersConfigurer} is gone).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:253` - TODO: Migration required - samlFilterChain/filterChain/configureSecurity built the Spring SecurityFilterChain instances. Their behaviour is summarised in the class javadoc and must be reimplemented via Quarkus HTTP auth config + filters/IdentityProviders. The full original DSL is preserved in version control. No fabricated SecurityFilterChain is produced here.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:262` - Produces the IP rate-limiting filter (plain {@code jakarta.servlet.Filter}, not a Spring-specific type, so it remains a CDI producer). TODO: Migration required - registration/ordering must be handled by quarkus-undertow ({@code @WebFilter}) or a {@code ContainerRequestFilter}. This filter was already disabled in the original chain (limit is effectively a no-op at 1,000,000) pending conversion.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:289` - TODO: Migration required - JwtAuthenticationFilter is @ApplicationScoped with CDI field injection; CDI manages it directly. The @Produces factory was removed because constructing it here with explicit args is incompatible with how the bean is declared. Inject JwtAuthenticationFilter directly wherever it is needed.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AuthController.java:328` - TODO: Migration required - SecurityContextHolder.clearContext() has no Quarkus equivalent; SecurityIdentity is request-scoped and not cleared imperatively. Cookie/ token invalidation is handled by the JWT cookie being dropped by the client/filter.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/EnterpriseEndpointFilter.java:21` - Spring's OncePerRequestFilter has no Quarkus equivalent; implementing jakarta.servlet.Filter directly. Registered via @WebFilter (quarkus-undertow). The single-execution-per-request guarantee OncePerRequestFilter provided is effectively given for top-level servlet filters here. TODO: Migration required - if this filter must run before/after other filters, ordering is not expressed by @WebFilter; configure quarkus.http.filter.* or a ServletExtension if order matters.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/JwtAuthenticationFilter.java:47` - TODO: Migration required - registration/ordering. As a Spring OncePerRequestFilter this ran once per request at a Spring-defined position in the security filter chain. On Quarkus (quarkus-undertow) a jakarta.servlet.Filter needs explicit registration and ordering (e.g. a @WebFilter with urlPatterns, or a FilterRegistrationBean-style producer). Confirm this filter is registered ahead of the resource layer and that the once-per-request semantics are preserved (Undertow does not re-enter servlet...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/JwtAuthenticationFilter.java:150` - TODO: Migration required - SecurityContextHolder has no Quarkus equivalent. This reads/writes the Spring thread-local security context. On Quarkus, the identity should come from SecurityIdentity (injected) and API-key auth should be handled by a custom IdentityProvider rather than imperatively setting the context.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/JwtAuthenticationFilter.java:176` - TODO: Migration required - the previous ApiKeyAuthenticationToken extended Spring Security's AbstractAuthenticationToken. It is now a plain POJO that does not implement the security-compat Authentication contract, so it cannot be stored in the SecurityContext. Build a compat UsernamePasswordAuthenticationToken from the user's authorities to keep the API-key authentication intent; in Quarkus this should be a SecurityIdentity produced by a custom IdentityProvider for the API key.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/JwtAuthenticationFilter.java:220` - TODO: Migration required - SecurityContextHolder/UsernamePasswordAuthenticationToken. Building a Spring authentication token and pushing it into the thread-local context must be replaced by producing a Quarkus SecurityIdentity (via IdentityProvider/ SecurityIdentityAugmentor) from the validated JWT claims. The user-loading logic (userDetailsService.loadUserByUsername) can be kept as a plain service call.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/JwtAuthenticationFilter.java:243` - TODO: Migration required - Spring's WebAuthenticationDetailsSource (remote address + session id) has no Quarkus equivalent. Storing the request as the details object keeps the call compile-safe; in Quarkus this metadata is available from the RoutingContext / SecurityIdentity.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/ParticipantRateLimitInterceptor.java:71` - Do not trust X-Forwarded-For: it is user-controlled and trivially spoofed, which would allow an attacker to bypass this rate limiter by rotating fake IPs. Operators who deploy behind a trusted reverse proxy should configure Quarkus' quarkus.http.proxy.* (proxy-address-forwarding / trusted-proxies) at the framework level instead. TODO: Migration required - ContainerRequestContext does not expose the remote address. Inject quarkus' RoutingContext (io.vertx.ext.web.RoutingContext) or jakarta.ser...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java:40` - TODO: Migration required - @Profile("!saas") had no direct annotation equivalent here. Gate this filter's activation on the "saas" build profile (e.g. via @io.quarkus.arc.profile.UnlessBuildProfile or a runtime check) and register it through Quarkus (quarkus-undertow @WebFilter or a jakarta.ws.rs.container.ContainerRequestFilter @Provider). Registration ordering relative to the other security filters (JwtAuthenticationFilter, *RateLimitingFilter) must be preserved.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java:83` - Start each request clean so a pooled thread can't inherit a prior request's key label - but keep a label an upstream filter (JwtAuthenticationFilter) already set for a request it API-key-authenticated. TODO: Migration required - ApiKeyAuthenticationToken is a plain POJO here, so "already authenticated upstream" is the closest available test.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java:90` - Spring's OncePerRequestFilter#shouldNotFilter behavior: skip the filter body for static resources, SPA routes and public API endpoints. TODO: Migration required - ensure the Quarkus filter registration does not run this filter more than once per request (the OncePerRequestFilter guarantee).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java:319` - Was Spring's OncePerRequestFilter#shouldNotFilter; now called explicitly at the top of doFilter. TODO: Migration required - if registered as a ContainerRequestFilter instead of a servlet Filter, fold this skip logic into the request filter using UriInfo.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java:32` - Servlet filter retained (quarkus-undertow). Spring's OncePerRequestFilter replaced by a plain jakarta.servlet.Filter registered as a CDI bean via @WebFilter so it covers all requests; the rate-limiting logic operates on the raw HttpServletRequest/HttpServletResponse which a JAX-RS ContainerRequestFilter does not expose as conveniently. TODO: Migration required - Spring's @Profile("!saas") gated this filter so it was NOT registered in the "saas" profile. Quarkus has no per-profile bean exclusi...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java:48` - TODO: Migration required - SecurityContextHolder replaced by injected SecurityIdentity. SecurityIdentity is request-scoped and is populated by Quarkus security extensions (quarkus-elytron-security / quarkus-oidc / etc.) once authentication is migrated. Until then it will be anonymous and getRoleFromIdentity will fall through to the IllegalStateException.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/model/ApiKeyAuthenticationToken.java:6` - TODO: Migration required - this class extended Spring Security's org.springframework.security.authentication.AbstractAuthenticationToken (which implements org.springframework.security.core.Authentication). Quarkus has no equivalent token type; the runtime principal model is io.quarkus.security.identity.SecurityIdentity, typically built via a custom IdentityProvider / SecurityIdentityAugmentor for the API-key auth path. This class has been reduced to a plain POJO that preserves the principal/c...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/TauriAuthorizationRequestResolver.java:6` - TODO: Migration required - this class implemented Spring Security's org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver SPI, wrapping DefaultOAuth2AuthorizationRequestResolver (built from a ClientRegistrationRepository) to inject a custom "tauri:" state value before the authorization request is sent to the OAuth2 provider. quarkus-oidc has no equivalent pluggable AuthorizationRequestResolver SPI. The Spring glue (OAuth2AuthorizationRequestResolver, DefaultOAuth2A...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java:167` - Resolve through the shared service (multi-key table, then the legacy per-user column). The key runs as its owner with the owner's authorities. TODO: Migration required - emits a Spring-shaped Authentication consumed by the auth filters; replace with a SecurityIdentity construction once the filter layer is ported.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java:25` - TODO: Migration required - this class implements the SessionRegistry compatibility shim (stirling.software.common.security.SessionRegistry) and exposes SessionInformation, UserDetails and OAuth2User from the same compat package. Quarkus has no equivalent session-registry abstraction. These shim types are kept ONLY because un-migrated collaborators (UserAuthenticationFilter, UserService, SessionRegistryConfig) still consume this interface and its return types. Once those collaborators are migr...
- `app/proprietary/src/main/java/stirling/software/proprietary/web/AuditWebFilter.java:25` - Servlet filter retained (quarkus-undertow). Spring's OncePerRequestFilter replaced by a plain jakarta.servlet.Filter registered as a CDI bean via @WebFilter so it covers all requests. TODO: Migration required - Spring's @Order(Ordered.HIGHEST_PRECEDENCE + 10) ordering has no direct @WebFilter equivalent; if this filter must run before other servlet filters, configure ordering explicitly (e.g. via a FilterRegistrationBean equivalent / quarkus.http.filter.* in application.properties).
- `app/proprietary/src/main/java/stirling/software/proprietary/web/CorrelationIdFilter.java:22` - TODO: Migration required - quarkus-undertow provides jakarta.servlet support. Register this filter and its URL mapping/ordering via a @WebFilter annotation or a ServletExtension if order matters (Spring auto-registered @Component filters; Quarkus does not).
- `app/saas/build.gradle:14` - spring-boot-starter-webmvc -> quarkus-rest (inherited api-scoped from :common). REMOVED: spring-boot-starter-aspectj - no AspectJ in Quarkus; use quarkus-arc CDI interceptors. TODO: Migration required - rewrite any @Aspect advice (e.g. CreditSuccessAdvice) as CDI interceptors.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:75` - TODO: Migration required - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:109` - TODO: Migration required - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:141` - TODO: Migration required - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:189` - TODO: Migration required - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:244` - TODO: Migration required - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:268` - TODO: Migration required - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:344` - TODO: Migration required - @PreAuthorize("@teamSecurity.isTeamMember(#teamId)") complex SpEL; enforce team-membership check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:363` - TODO: Migration required - @PreAuthorize("@teamSecurity.isTeamLeader(#teamId)") complex SpEL; enforce team-leader check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:382` - TODO: Migration required - @PreAuthorize("@teamSecurity.isTeamLeader(#teamId)") complex SpEL; enforce team-leader check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:436` - TODO: Migration required - @PreAuthorize("@teamSecurity.isTeamMember(#teamId)") complex SpEL; enforce team-membership check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:485` - TODO: Migration required - @PreAuthorize("@teamSecurity.isTeamLeader(#teamId)") complex SpEL; enforce team-leader check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:727` - TODO: Migration required - @PreAuthorize("@teamSecurity.isTeamMember(#teamId) or hasRole('ADMIN')") complex SpEL; enforce team-membership-or-admin check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/UserRoleWebhookController.java:195` - TODO: Migration required - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter. TODO: Migration required - inject Principal via @jakarta.ws.rs.core.Context SecurityContext (JAX-RS does not bind a bare java.security.Principal parameter like Spring MVC).
- `app/saas/src/main/java/stirling/software/saas/payg/api/PaygWalletController.java:72` - cap is enforced application-side via the entitlement guard) and invalidates the team's snapshot cache. Only leaders may call this; the team is derived from the caller, so we authorise inside the method — the team id never appears on the path or query string. TODO: Migration required - was a Spring {@code @RestController} with method-injected {@code Authentication} and {@code @PreAuthorize("isAuthenticated()")}. Now JAX-RS: auth comes from the {@link SecurityContextHolder} thread-local shim (p...
- `app/saas/src/main/java/stirling/software/saas/payg/cap/AiToolRoutes.java:29` - TODO: Migration required - literal value of the former Spring constant HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE. Replace with the JAX-RS route template (UriInfo / ResourceInfo) once the interceptor is converted to a @Provider filter.
- `app/saas/src/main/java/stirling/software/saas/payg/charge/JobInput.java:30` - TODO: Migration required - Part/MultipartFile bridge. The ingress interceptor (PaygChargeInterceptor) is now servlet-native and constructs inputs from jakarta.servlet.http.Part rather than Spring's MultipartFile. The downstream classifier still consumes the stirling.software.common.model.MultipartFile abstraction (size + content-type + input stream). This constructor adapts a Part into that abstraction so both the untouched interceptor and the classifier compile/run. Longer term, JobInput sho...
- `app/saas/src/main/java/stirling/software/saas/payg/entitlement/EntitlementGuard.java:64` - pipeline must never block a customer because the guard tripped on a transient DB error. TODO: Migration required - was a Spring {@code @Component} implementing {@code HandlerInterceptor}. Convert to a JAX-RS {@code @Provider} ContainerRequestFilter (priority {@code PaygWebMvcConfig.ENTITLEMENT_GUARD_ORDER}). Handler-annotation introspection now uses a reflective {@link Method} fallback; HTTP status/header/media-type constants are inlined literals.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:69` - and counted on {@code payg.filter.errors}. The customer's tool call always proceeds. TODO: Migration required - was a Spring {@code @Component} ({@code @Profile("saas")}) implementing {@code AsyncHandlerInterceptor}. Convert to a JAX-RS {@code @Provider} request/response filter pair. Handler-annotation introspection now uses a reflective {@link Method} fallback (see {@link #resolveResourceMethod}); multipart access uses the servlet-native {@link Part} API ({@code request.getParts()}); the bes...
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:91` - TODO: Migration required - literal value of the former Spring constant {@code HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE}. Replace with the JAX-RS route template obtained from {@code @Context UriInfo} / {@code ResourceInfo} during the filter conversion.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:181` - TODO: Migration required - was @Override AsyncHandlerInterceptor#preHandle(request, response, handler). Convert to a JAX-RS ContainerRequestFilter.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:242` - TODO: Migration required - was `request instanceof MultipartHttpServletRequest mreq` + mreq.getMultiFileMap(). Now uses servlet-native request.getParts(). A non-multipart request yields no file parts and short-circuits, preserving the original behavior.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:332` - TODO: Migration required - the {@link JobInput} record's first component is still Spring's {@code MultipartFile} (owned by another module). This interceptor now sources inputs from the servlet {@link Part} API. Once {@code JobInput} is migrated to carry a {@link Part} (or a neutral size+content-type holder), construct it directly here: {@code return new JobInput(part, path);}. Kept as a single adaptation seam so the rest of the charge flow is untouched.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:343` - TODO: Migration required - was @Override AsyncHandlerInterceptor#afterCompletion(request, response, handler, Exception). Convert to a JAX-RS ContainerResponseFilter.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:488` - TODO: Migration required - was @Override AsyncHandlerInterceptor#afterConcurrentHandlingStarted. JAX-RS handles async dispatch differently; no direct equivalent required.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygFilterProperties.java:24` - TODO: Migration required - @ConfigurationProperties(prefix="payg.filter"); bind via @ConfigProperty or @ConfigMapping
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygResponseBodyWrapperFilter.java:33` - TODO: Migration required - this was a Spring {@code OncePerRequestFilter} ({@code @Component @Profile("saas")}). It must be re-registered as a {@code jakarta.servlet.Filter} (or a JAX-RS {@code @jakarta.ws.rs.ext.Provider} ContainerResponse filter pair) and ordered ahead of the PAYG interceptor so the response wrapper is available in afterCompletion. The Spring base class provided once-per-request dispatch and the {@code doFilterInternal} hook; that hook's servlet signature is retained below ...
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygResponseBodyWrapperFilter.java:61` - TODO: Migration required - was @Override of Spring OncePerRequestFilter#doFilterInternal. Retains the servlet signature; invoke from the filter registration's doFilter once converted.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygWebMvcConfig.java:13` - Holds the PAYG hot-path ordering constants. Under Spring MVC these registered {@link PaygChargeInterceptor} and the entitlement guard as ordered interceptors; under Quarkus the interceptor/guard are JAX-RS filters that self-order via {@code @Priority}. The order constants remain the single source of truth for that relative ordering. TODO: Migration required - the Spring {@code WebMvcConfigurer#addInterceptors} registration was removed. Re-express it as JAX-RS {@code @Provider} ContainerReques...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:55` - Stateless JWT authentication filter for the saas profile. TODO: Migration required - this was a Spring {@code OncePerRequestFilter}. It must be re-registered as a JAX-RS {@code @jakarta.ws.rs.container.ContainerRequestFilter} with {@code @jakarta.ws.rs.ext.Provider} (or a {@code jakarta.servlet.Filter}) and ordered before the Quarkus OIDC/auth processing. The {@code doFilterInternal}/{@code shouldNotFilter} servlet signatures are retained here; the request/response handling and entry-point er...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:72` - TODO: Migration required - placeholder for Spring's {@code org.springframework.security.oauth2.jwt.JwtDecoder}. Replace with Quarkus OIDC token parsing that yields a verified {@link JsonWebToken} (or throws on invalid token).
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:88` - TODO: Migration required - the Spring AuthenticationEntryPoint (BearerTokenAuthenticationEntryPoint) that wrote the 401 challenge has no Quarkus equivalent here. When converting to a JAX-RS @Provider filter, emit the 401 / WWW-Authenticate response directly (or delegate to Quarkus OIDC) in place of authenticationEntryPoint.commence(...).
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:108` - TODO: Migration required - this retains the original OncePerRequestFilter.doFilterInternal behavior. Wire it into a JAX-RS ContainerRequestFilter / servlet Filter. The error branch previously called authenticationEntryPoint.commence(request, response, e); emit the 401 response directly during that conversion.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:143` - TODO: Migration required - was authenticationEntryPoint.commence(request, response, e) (Spring BearerTokenAuthenticationEntryPoint). Emit the 401 challenge response here when converting to a JAX-RS @Provider filter.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:219` - TODO: Migration required - previously caught Spring's JwtException and rethrew InvalidBearerTokenException("Invalid JWT", e). Adjust to the exception type thrown by the Quarkus OIDC token parser.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:313` - TODO: Migration required - was Spring's DataIntegrityViolationException (email-collision race). jakarta.persistence.PersistenceException is broader; narrow to the Hibernate/JPA constraint-violation type once the persistence layer is finalized.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:409` - Concurrent creation; fall through, the row exists. TODO: Migration required - was Spring's DataIntegrityViolationException. Narrow to the Hibernate/JPA constraint-violation type once the persistence layer is finalized.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:424` - Parallel filter won the race; fetch the winning row. TODO: Migration required - was Spring's DataIntegrityViolationException. Narrow to the Hibernate/JPA constraint-violation type once the persistence layer is finalized.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:457` - TODO: Migration required - ApiKeyAuthenticationToken is a plain POJO that does not implement the Authentication shim. Wrap the principal/credentials/authorities in a UsernamePasswordAuthenticationToken (which does) so it can be set on the SecurityContext. Re-wire to a Quarkus SecurityIdentity when the API-key auth path is migrated.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:483` - --------------------------------------------------------------------------------------------- TODO: Migration required - claim accessor adapters. Spring's Jwt exposed typed claim getters (getClaimAsString/getClaimAsStringList/getClaimAsInstant/getClaimAsBoolean). MicroProfile JsonWebToken only exposes a generic getClaim(name); these helpers reproduce the original typed semantics so the validation/user-creation logic is preserved unchanged. -----------------------------------------------------...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseSecurityConfig.java:38` - Stateless Supabase-JWT security chain. TODO: Migration required - this class was a Spring {@code @Configuration} with {@code @EnableWebSecurity}, {@code @EnableMethodSecurity}, {@code @Profile("saas")} and {@code @Order(1)}. The {@code SecurityFilterChain} bean (CSRF/CORS/session/oauth2ResourceServer wiring) has no Quarkus equivalent and must be re-expressed declaratively via {@code quarkus.http.auth.*} config plus Quarkus OIDC/SmallRye-JWT. The {@code SecurityFilterChain} bean method has bee...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseSecurityConfig.java:72` - TODO: Migration required - the original @Bean SecurityFilterChain saasSecurityFilterChain(...) configured CSRF-disabled, CORS, STATELESS sessions, permitAll matchers for OPTIONS/actuator-health/config/static/public-auth/frontend routes, anyRequest().authenticated(), registered SupabaseAuthenticationFilter before BearerTokenAuthenticationFilter, set a BearerTokenAuthenticationEntryPoint + BearerTokenAccessDeniedHandler, and wired oauth2ResourceServer().jwt() with this JwtDecoder and SupabaseSe...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseSecurityConfig.java:168` - TODO: Migration required - original @Bean CorsConfigurationSource configured CORS for the Spring SecurityFilterChain (allowed origins/methods/headers, exposed header WWW-Authenticate, allowCredentials=true, maxAge=3600). Re-express via quarkus.http.cors.* properties. The origin-resolution logic (operator override vs. defaults, the Tauri desktop origins, and the wildcard warning) is retained below as a helper for that translation.
- `app/common/build.gradle:11` - Servlet bridge: large amounts of controller/filter code use jakarta.servlet (HttpServletRequest, Filter, etc.). quarkus-undertow provides a servlet container on Quarkus so that API resolves and runs. longer term, port servlet usage to JAX-RS (ContainerRequestContext) and drop quarkus-undertow.
- `app/common/build.gradle:27` - REMOVED: spring-boot-starter-aspectj. Quarkus has no AspectJ weaving; quarkus-arc provides CDI interceptors (@AroundInvoke / interceptor bindings) instead. any @Aspect/@Around advice must be rewritten as CDI interceptors.
- `app/core/src/main/java/stirling/software/SPDF/config/LocaleConfiguration.java:11` - this class was a Spring MVC WebMvcConfigurer. Quarkus/JAX-RS has no WebMvcConfigurer, InterceptorRegistry, LocaleChangeInterceptor or SessionLocaleResolver. The locale-resolution logic (computing the default Locale from configuration) is preserved below as a CDI-produced Locale. The two pieces of behavior that previously came from the MVC machinery still need to be wired up by collaborators: 1. The "lang" request-param locale ...
- `app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java:38` - are read automatically, so this class is now an {@link OASFilter} (registered via {@code mp.openapi.filter} in application.properties) that reproduces the old programmatic customizations: <ul> <li>API {@link Info} (title, version, license, contact, terms of service, description); <li>the global "AI" {@link Tag}; <li>the {@link Server} entry (optionally from {@code SWAGGER_SERVER_URL}); <li>the {@code ErrorResponse} component schema; <li>the {@code apiKey} ...
- `app/core/src/main/java/stirling/software/SPDF/config/SpringDocConfig.java:3` - springdoc's GroupedOpenApi (multiple OpenAPI documents grouped by path-matching) has NO direct equivalent in quarkus-smallrye-openapi, which serves a single document built automatically from @Tag/@Operation/JAX-RS annotations. The three groups below (file-processing "/api/v1/**" minus management/system paths, management "/api/v1/admin/**" etc., and system "/api/v1/ui-data/**" etc.) plus the pdfFileOneOfCustomizer ...
- `app/core/src/main/java/stirling/software/SPDF/config/WAUTrackingFilter.java:21` - Spring @ConditionalOnProperty(name="security.enableLogin", havingValue="false") had no direct CDI equivalent for conditional bean registration. The filter is now always registered (@Provider) and the condition is enforced at request time by reading the 'security.enableLogin' config property below. Verify the property key matches Quarkus config (originally bound from ApplicationProperties.security.enableLogin).
- `app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java:63` - in Spring, addResourceHandlers also registered the physical resource locations (InstallationPathConfig.getStaticPath() + "classpath:/static/") and an EncodedResourceResolver (gzip/brotli pre-compressed asset serving). In Quarkus, static file serving is handled by quarkus.http via configuration: quarkus.http.static-resources... and/or a Servlet/RouteFilter mapping InstallationPathConfig.getStaticPath() as an external static root ...
- `app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java:152` - Quarkus has built-in CORS handling via quarkus.http.cors.* config properties (quarkus.http.cors.origins, .methods, .headers, .exposed-headers, .access-control-allow-credentials, .access-control-max-age). However, the original logic is *dynamic* (Tauri-mode detection + ApplicationProperties-driven origins + always-on Tauri origins), which static config cannot express. The logic is preserved below and applied via this response ...
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:106` - the per-request locale used to come from Spring's LocaleContextHolder (populated by the MVC LocaleChangeInterceptor). Until the equivalent ContainerRequestFilter described in LocaleConfiguration is in place, fall back to the JVM default locale. Localized messages are read from the shared messages.properties bundle (the same bundle ExceptionUtils uses) instead of a Spring MessageSource bean, which no longer exists under Quarkus.
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:806` - the original Spring handler checked HttpServletResponse.isCommitted() and returned null to let Spring write nothing when the response was already committed (e.g. during streaming). JAX-RS ExceptionMapper has no direct access to commit state; returning a Response here is the closest equivalent. If streaming endpoints need the old "do nothing when committed" behavior, a collaborator should detect that condition (e.g. via a ...
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:873` - locale is the JVM default until the per-request locale ContainerRequestFilter described in LocaleConfiguration replaces Spring's LocaleContextHolder.getLocale().
- `app/core/src/main/resources/application.properties:46` - no direct Quarkus equivalent for the following; handle in code: - spring.threads.virtual.enabled=true -> annotate blocking endpoints with @RunOnVirtualThread - spring.mvc.async.request-timeout -> per-endpoint timeout handling - spring.security.filter.dispatcher-types=REQUEST,ERROR - spring.web.resources.mime-mappings.webmanifest=application/manifest+json - server.servlet.session.tracking-modes=cookie (configure on ...
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:34` - {@code @Around("@annotation(...Audited)")} advice. Reworked into a CDI {@link Interceptor} bound by the {@code @Audited} annotation; {@code @Around}/{@code ProceedingJoinPoint} became {@code @AroundInvoke}/{@link InvocationContext}. Spring's {@code @Order(10)} (lower precedence, runs after {@code AutoJobAspect}) maps to {@code @Priority}: {@code AutoJobAspect} uses {@code @Priority(20)}, so this audit interceptor uses {@code @Priority(10)} which runs ...
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:41` - stirling.software.proprietary.audit.Audited}) must be made a CDI {@code @jakarta.interceptor.InterceptorBinding} (and its members marked {@code @jakarta.enterprise.util.Nonbinding}) for this {@code @Interceptor} to bind to it; see the already-migrated {@code AutoJobPostMapping}. That is a separate file and is intentionally left untouched here. {@code AuditService}'s helper methods ({@code createBaseAuditData}, {@code ...
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/ControllerAuditAspect.java:38` - multiple {@code @Around} advice whose pointcuts matched <em>any</em> method annotated with Spring's {@code @GetMapping}/{@code @PostMapping}/{@code @PutMapping}/{@code @DeleteMapping}/ {@code @PatchMapping}/{@code @AutoJobPostMapping}, plus an {@code execution(...)} expression on Spring's {@code ResourceHttpRequestHandler}. {@code @Around}/{@code ProceedingJoinPoint} + {@code MethodSignature} became {@code @AroundInvoke}/{@link InvocationContext}, and ...
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/ControllerAuditAspect.java:204` - (collaborator) - AuditService.createBaseAuditData/addFileData/ addMethodArguments/resolveEventType still take org.aspectj.lang.ProceedingJoinPoint (AuditService is not yet migrated). Once AuditService is converted, change those signatures to accept jakarta.interceptor.InvocationContext (getMethod/getParameters/ getTarget cover the data used). These calls pass the InvocationContext and will only typecheck after that collaborator ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpApiKeyAuthFilter.java:42` - Spring Security removed. This filter previously read the current Authentication from SecurityContextHolder to decide whether to process the API key. Quarkus has no SecurityContextHolder; the current identity is exposed via io.quarkus.security.identity.SecurityIdentity. With the binding below not yet wired, we always attempt to validate the presented key so the lookup logic is preserved.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpApiKeyAuthFilter.java:51` - bind the resolved user + MCP_SCOPES to the request identity. Spring's UsernamePasswordAuthenticationToken / SecurityContextHolder.setContext(...) has no servlet-filter equivalent in Quarkus. Implement an io.quarkus.security.identity.SecurityIdentityAugmentor (or a custom io.quarkus.vertx.http.runtime.security.HttpAuthenticationMechanism / IdentityProvider keyed off the X-API-KEY / Bearer credential) that produces a ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpAudienceValidator.java:14` - RFC 8707 audience binding: a JWT at the MCP endpoint must list this server's resource id (or one of the explicitly accepted additional audiences) in its {@code aud} claim. The additional list exists for IdPs that cannot mint resource-specific audiences - e.g. Supabase's OAuth server always issues {@code aud=authenticated}. Fails closed when nothing is configured. this was a Spring Security {@code OAuth2TokenValidator<Jwt>} ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpAuthenticationEntryPoint.java:17` - Emits 401 + {@code WWW-Authenticate: Bearer resource_metadata="..."} (RFC 9728) from X-Forwarded-* headers. A rejected token also logs the reason and echoes it as {@code error_description}. this was a Spring Security {@code AuthenticationEntryPoint} (commence(...) invoked by the SecurityFilterChain on authentication failure). Quarkus has no SecurityFilterChain equivalent. The 401 response must instead be produced by a Quarkus ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpRequestSizeFilter.java:27` - this filter was a Spring OncePerRequestFilter; under Quarkus (quarkus-undertow) register it as a jakarta.servlet.Filter via @WebFilter or a programmatic FilterRegistrationBean equivalent, and ensure it runs once per request and before the MCP endpoint. Registration ordering must be verified by the collaborator wiring the servlet filters.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpSecurityConfig.java:15` - MCP security chain: validates JWTs (JWKS + RFC 8707 audience), maps scope claims to authorities, and fails closed when the issuer is unset. this class was a Spring Security {@code SecurityFilterChain} / {@code HttpSecurity} DSL configuration, which has NO direct Quarkus equivalent. The Spring security DSL has been removed; the equivalent behaviour must be rebuilt on Quarkus primitives: <ul> <li>HTTP path matching ({@code /mcp} ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpSecurityConfig.java:57` - @Order(Ordered.HIGHEST_PRECEDENCE) and @ConditionalOnProperty(name = "mcp.enabled", havingValue = "true") were removed. Gate MCP security wiring on the runtime property mcp.enabled=true (a runtime toggle, not a build profile, so prefer a runtime guard in the new ContainerRequestFilter/augmentor). Filter ordering (highest precedence) must be re-expressed via JAX-RS @Priority or quarkus.http.auth.permission ordering.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpSecurityConfig.java:66` - UserService was injected @Lazy to break a circular wiring with the security chain. With the Spring chain removed, inject it directly into the new API-key / user-binding ContainerRequestFilters instead of holding it here.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpUserBindingFilter.java:26` - Binds an MCP-validated JWT to a provisioned Stirling user: optionally rejects subjects with no enabled account, then rebinds the principal to the canonical Stirling username (scope authorities only) so audit/metering attribute correctly. this was a Spring Security {@code OncePerRequestFilter} that read and rewrote the {@code SecurityContextHolder} ({@code JwtAuthenticationToken}/{@code Jwt}). Quarkus has no global mutable ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpUserBindingFilter.java:60` - extract the validated JWT and its claims from the Quarkus SecurityIdentity / JsonWebToken instead of Spring's SecurityContextHolder. The block below preserves the original binding logic but cannot run until that wiring exists, so for now every request passes through untouched.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpUserBindingFilter.java:66` - read the claim value from the validated token, e.g. jsonWebToken.getClaim(usernameClaim). Placeholder keeps the surrounding logic intact.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpUserBindingFilter.java:98` - rebind to the Stirling username, carrying only the OAuth scope authorities. With quarkus-oidc/smallrye-jwt this is done by a SecurityIdentityAugmentor that returns a new SecurityIdentity whose principal name is boundUsername and whose roles are the original token scopes. boundUsername is computed above and ready to feed into that augmentor.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpUserBindingFilter.java:116` - on the Quarkus path, rejection should clear/deny the SecurityIdentity (augmentor throws AuthenticationFailedException) or the ContainerRequestFilter should abortWith(Response.status(403)...). The 403 JSON body below is preserved as the intended response shape.
- `app/proprietary/src/main/java/stirling/software/proprietary/repository/PersistentAuditEventRepository.java:333` - --------------------------------------------------------------------- Multi-value queries for filtering by multiple types and/or principals callers must adapt to the PanacheQuery return type (see class doc). ---------------------------------------------------------------------
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:21` - this class extended Spring Security's SimpleUrlAuthenticationFailureHandler and was wired into the form-login SecurityFilterChain. Quarkus has no direct equivalent for an AuthenticationFailureHandler. The login-failure flow (lockout, bad credentials, oauth2 errors, disabled users) must be re-hosted on a Quarkus authentication mechanism - typically a custom form-auth (quarkus.http.auth.*) or quarkus-oidc - with the redirect ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java:24` - this class previously extended Spring Security's SavedRequestAwareAuthenticationSuccessHandler, which is part of the Spring Security form-login filter chain (RedirectStrategy + SavedRequest from the HttpSession). Quarkus has no direct equivalent: post-login redirects are handled by quarkus-oidc / form-auth (quarkus.http.auth.form.landing-page, .location-cookie) or by a custom jakarta.servlet.Filter / ContainerRequestFilter / ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java:89` - "SPRING_SECURITY_SAVED_REQUEST" was populated by the Spring Security RequestCache. Without the Spring filter chain this attribute is never set, so this branch always falls through to the home-page redirect. The original-destination redirect must be reimplemented via the Quarkus form-auth location cookie or a custom request cache.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/JwtAuthenticationEntryPoint.java:9` - this was a Spring Security AuthenticationEntryPoint (org.springframework.security.web.AuthenticationEntryPoint). Quarkus has no direct AuthenticationEntryPoint SPI; unauthenticated-access handling is wired via quarkus.http.auth.* policies and an AuthenticationFailedException mapper / a jakarta.ws.rs.ext.ExceptionMapper<io.quarkus.security.UnauthorizedException> (or a ContainerRequestFilter). The response-shaping logic below is ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/config/EnterpriseEndpointAspect.java:23` - MIGRATION (Spring AOP -> CDI interceptor): was an {@code @Aspect} {@code @Component} with {@code @Around} advice matching {@code @annotation(EnterpriseEndpoint)} / {@code @within(EnterpriseEndpoint)}. Reworked into a CDI {@link Interceptor} bound by the {@code @EnterpriseEndpoint} annotation (pattern: common/aop/AutoJobAspect). {@code @Around} + {@code ProceedingJoinPoint} became {@code @AroundInvoke} + {@link InvocationContext}; {@code ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/config/PremiumEndpointAspect.java:20` - MIGRATION (Spring AOP -> CDI interceptor): was an {@code @Aspect} with {@code @Around} advice on the {@code @PremiumEndpoint} pointcut ({@code @annotation || @within}). Reworked into a CDI {@link Interceptor} bound by the {@code @PremiumEndpoint} {@code @InterceptorBinding}; {@code @Around}/{@code ProceedingJoinPoint} became {@code @AroundInvoke}/{@link InvocationContext}. The Spring {@code ResponseStatusException(HttpStatus.FORBIDDEN, ...)} became a ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ProprietaryWebMvcConfig.java:10` - Spring MVC's WebMvcConfigurer / InterceptorRegistry has no Quarkus (JAX-RS / RESTEasy Reactive) equivalent, so this registration class cannot be ported directly.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ProprietaryWebMvcConfig.java:30` - the interceptor registration below was removed: registry.addInterceptor(participantRateLimitInterceptor) .addPathPatterns("/api/v1/workflow/participant/**"); Re-implement as a JAX-RS ContainerRequestFilter bound to that path (see class javadoc).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:31` - Security configuration migrated from a Spring {@code @Configuration}/{@code @EnableWebSecurity} class to a Quarkus CDI bean. This class was built entirely around the Spring Security {@code HttpSecurity} DSL and {@code SecurityFilterChain} beans, which have NO direct Quarkus equivalent. The HTTP security model must be re-expressed declaratively/imperatively: <ul> <li><b>HTTP path policies / authorization</b> (the {@code ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:95` - reusable, non-Spring helper logic (CORS values, X-Frame-Options decision, firewall char patterns, filter/repository factories) is retained as plain methods/producers below. this bean was {@code @DependsOn("runningProOrHigher")} and {@code @Profile("!saas")}. The dependency ordering is approximated by injecting the {@code runningProOrHigher} flag; the {@code !saas} profile gate maps to a Quarkus build profile - use {@code ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:176` - Reusable CORS settings preserved from the original {@code corsConfigurationSource()} bean. the Spring {@code CorsConfigurationSource}/ {@code UrlBasedCorsConfigurationSource} types are removed. Apply these values via {@code quarkus.http.cors.*} in {@code application.properties} (origins, methods, headers, exposed-headers, access-control-allow-credentials=true, access-control-max-age=PT1H) or a {@code ContainerResponseFilter} ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:230` - Resolves the desired X-Frame-Options header value, preserving the original decision logic. apply the returned value via a response filter or {@code quarkus.http.header} config (Spring's {@code HeadersConfigurer} is gone).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:253` - samlFilterChain/filterChain/configureSecurity built the Spring SecurityFilterChain instances. Their behaviour is summarised in the class javadoc and must be reimplemented via Quarkus HTTP auth config + filters/IdentityProviders. The full original DSL is preserved in version control. No fabricated SecurityFilterChain is produced here.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:262` - Produces the IP rate-limiting filter (plain {@code jakarta.servlet.Filter}, not a Spring-specific type, so it remains a CDI producer). registration/ordering must be handled by quarkus-undertow ({@code @WebFilter}) or a {@code ContainerRequestFilter}. This filter was already disabled in the original chain (limit is effectively a no-op at 1,000,000) pending conversion.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:289` - JwtAuthenticationFilter is @ApplicationScoped with CDI field injection; CDI manages it directly. The @Produces factory was removed because constructing it here with explicit args is incompatible with how the bean is declared. Inject JwtAuthenticationFilter directly wherever it is needed.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AuthController.java:328` - SecurityContextHolder.clearContext() has no Quarkus equivalent; SecurityIdentity is request-scoped and not cleared imperatively. Cookie/ token invalidation is handled by the JWT cookie being dropped by the client/filter.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/EnterpriseEndpointFilter.java:21` - Spring's OncePerRequestFilter has no Quarkus equivalent; implementing jakarta.servlet.Filter directly. Registered via @WebFilter (quarkus-undertow). The single-execution-per-request guarantee OncePerRequestFilter provided is effectively given for top-level servlet filters here. if this filter must run before/after other filters, ordering is not expressed by @WebFilter; configure quarkus.http.filter.* or a ServletExtension if ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/JwtAuthenticationFilter.java:47` - registration/ordering. As a Spring OncePerRequestFilter this ran once per request at a Spring-defined position in the security filter chain. On Quarkus (quarkus-undertow) a jakarta.servlet.Filter needs explicit registration and ordering (e.g. a @WebFilter with urlPatterns, or a FilterRegistrationBean-style producer). Confirm this filter is registered ahead of the resource layer and that the once-per-request semantics are ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/JwtAuthenticationFilter.java:150` - SecurityContextHolder has no Quarkus equivalent. This reads/writes the Spring thread-local security context. On Quarkus, the identity should come from SecurityIdentity (injected) and API-key auth should be handled by a custom IdentityProvider rather than imperatively setting the context.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/JwtAuthenticationFilter.java:176` - the previous ApiKeyAuthenticationToken extended Spring Security's AbstractAuthenticationToken. It is now a plain POJO that does not implement the security-compat Authentication contract, so it cannot be stored in the SecurityContext. Build a compat UsernamePasswordAuthenticationToken from the user's authorities to keep the API-key authentication intent; in Quarkus this should be a SecurityIdentity produced by a custom ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/JwtAuthenticationFilter.java:220` - SecurityContextHolder/UsernamePasswordAuthenticationToken. Building a Spring authentication token and pushing it into the thread-local context must be replaced by producing a Quarkus SecurityIdentity (via IdentityProvider/ SecurityIdentityAugmentor) from the validated JWT claims. The user-loading logic (userDetailsService.loadUserByUsername) can be kept as a plain service call.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/JwtAuthenticationFilter.java:243` - Spring's WebAuthenticationDetailsSource (remote address + session id) has no Quarkus equivalent. Storing the request as the details object keeps the call compile-safe; in Quarkus this metadata is available from the RoutingContext / SecurityIdentity.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/ParticipantRateLimitInterceptor.java:71` - Do not trust X-Forwarded-For: it is user-controlled and trivially spoofed, which would allow an attacker to bypass this rate limiter by rotating fake IPs. Operators who deploy behind a trusted reverse proxy should configure Quarkus' quarkus.http.proxy.* (proxy-address-forwarding / trusted-proxies) at the framework level instead. ContainerRequestContext does not expose the remote address. Inject quarkus' RoutingContext ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java:40` - @Profile("!saas") had no direct annotation equivalent here. Gate this filter's activation on the "saas" build profile (e.g. via @io.quarkus.arc.profile.UnlessBuildProfile or a runtime check) and register it through Quarkus (quarkus-undertow @WebFilter or a jakarta.ws.rs.container.ContainerRequestFilter @Provider). Registration ordering relative to the other security filters (JwtAuthenticationFilter, *RateLimitingFilter) must be ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java:83` - Start each request clean so a pooled thread can't inherit a prior request's key label - but keep a label an upstream filter (JwtAuthenticationFilter) already set for a request it API-key-authenticated. ApiKeyAuthenticationToken is a plain POJO here, so "already authenticated upstream" is the closest available test.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java:90` - Spring's OncePerRequestFilter#shouldNotFilter behavior: skip the filter body for static resources, SPA routes and public API endpoints. ensure the Quarkus filter registration does not run this filter more than once per request (the OncePerRequestFilter guarantee).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java:319` - Was Spring's OncePerRequestFilter#shouldNotFilter; now called explicitly at the top of doFilter. if registered as a ContainerRequestFilter instead of a servlet Filter, fold this skip logic into the request filter using UriInfo.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java:32` - Servlet filter retained (quarkus-undertow). Spring's OncePerRequestFilter replaced by a plain jakarta.servlet.Filter registered as a CDI bean via @WebFilter so it covers all requests; the rate-limiting logic operates on the raw HttpServletRequest/HttpServletResponse which a JAX-RS ContainerRequestFilter does not expose as conveniently. Spring's @Profile("!saas") gated this filter so it was NOT registered in the "saas" profile ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java:48` - SecurityContextHolder replaced by injected SecurityIdentity. SecurityIdentity is request-scoped and is populated by Quarkus security extensions (quarkus-elytron-security / quarkus-oidc / etc.) once authentication is migrated. Until then it will be anonymous and getRoleFromIdentity will fall through to the IllegalStateException.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/model/ApiKeyAuthenticationToken.java:6` - this class extended Spring Security's org.springframework.security.authentication.AbstractAuthenticationToken (which implements org.springframework.security.core.Authentication). Quarkus has no equivalent token type; the runtime principal model is io.quarkus.security.identity.SecurityIdentity, typically built via a custom IdentityProvider / SecurityIdentityAugmentor for the API-key auth path. This class has been reduced to a ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/TauriAuthorizationRequestResolver.java:6` - this class implemented Spring Security's org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver SPI, wrapping DefaultOAuth2AuthorizationRequestResolver (built from a ClientRegistrationRepository) to inject a custom "tauri:" state value before the authorization request is sent to the OAuth2 provider. quarkus-oidc has no equivalent pluggable AuthorizationRequestResolver SPI. The Spring glue ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java:167` - Resolve through the shared service (multi-key table, then the legacy per-user column). The key runs as its owner with the owner's authorities. emits a Spring-shaped Authentication consumed by the auth filters; replace with a SecurityIdentity construction once the filter layer is ported.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java:25` - this class implements the SessionRegistry compatibility shim (stirling.software.common.security.SessionRegistry) and exposes SessionInformation, UserDetails and OAuth2User from the same compat package. Quarkus has no equivalent session-registry abstraction. These shim types are kept ONLY because un-migrated collaborators (UserAuthenticationFilter, UserService, SessionRegistryConfig) still consume this interface and its return ...
- `app/proprietary/src/main/java/stirling/software/proprietary/web/AuditWebFilter.java:25` - Servlet filter retained (quarkus-undertow). Spring's OncePerRequestFilter replaced by a plain jakarta.servlet.Filter registered as a CDI bean via @WebFilter so it covers all requests. Spring's @Order(Ordered.HIGHEST_PRECEDENCE + 10) ordering has no direct @WebFilter equivalent; if this filter must run before other servlet filters, configure ordering explicitly (e.g. via a FilterRegistrationBean equivalent / quarkus.http.filter.* ...
- `app/proprietary/src/main/java/stirling/software/proprietary/web/CorrelationIdFilter.java:22` - quarkus-undertow provides jakarta.servlet support. Register this filter and its URL mapping/ordering via a @WebFilter annotation or a ServletExtension if order matters (Spring auto-registered @Component filters; Quarkus does not).
- `app/saas/build.gradle:14` - spring-boot-starter-webmvc -> quarkus-rest (inherited api-scoped from :common). REMOVED: spring-boot-starter-aspectj - no AspectJ in Quarkus; use quarkus-arc CDI interceptors. rewrite any @Aspect advice (e.g. CreditSuccessAdvice) as CDI interceptors.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:75` - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:109` - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:141` - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:189` - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:244` - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:268` - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:344` - @PreAuthorize("@teamSecurity.isTeamMember(#teamId)") complex SpEL; enforce team-membership check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:363` - @PreAuthorize("@teamSecurity.isTeamLeader(#teamId)") complex SpEL; enforce team-leader check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:382` - @PreAuthorize("@teamSecurity.isTeamLeader(#teamId)") complex SpEL; enforce team-leader check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:436` - @PreAuthorize("@teamSecurity.isTeamMember(#teamId)") complex SpEL; enforce team-membership check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:485` - @PreAuthorize("@teamSecurity.isTeamLeader(#teamId)") complex SpEL; enforce team-leader check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:727` - @PreAuthorize("@teamSecurity.isTeamMember(#teamId) or hasRole('ADMIN')") complex SpEL; enforce team-membership-or-admin check programmatically or via a JAX-RS filter.
- `app/saas/src/main/java/stirling/software/saas/controller/UserRoleWebhookController.java:195` - @PreAuthorize("isAuthenticated()") complex SpEL; enforce authenticated access via JAX-RS SecurityContext / filter. inject Principal via @jakarta.ws.rs.core.Context SecurityContext (JAX-RS does not bind a bare java.security.Principal parameter like Spring MVC).
- `app/saas/src/main/java/stirling/software/saas/payg/api/PaygWalletController.java:72` - cap is enforced application-side via the entitlement guard) and invalidates the team's snapshot cache. Only leaders may call this; the team is derived from the caller, so we authorise inside the method — the team id never appears on the path or query string. was a Spring {@code @RestController} with method-injected {@code Authentication} and {@code @PreAuthorize("isAuthenticated()")}. Now JAX-RS: auth comes from the {@link ...
- `app/saas/src/main/java/stirling/software/saas/payg/cap/AiToolRoutes.java:29` - literal value of the former Spring constant HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE. Replace with the JAX-RS route template (UriInfo / ResourceInfo) once the interceptor is converted to a @Provider filter.
- `app/saas/src/main/java/stirling/software/saas/payg/charge/JobInput.java:30` - Part/MultipartFile bridge. The ingress interceptor (PaygChargeInterceptor) is now servlet-native and constructs inputs from jakarta.servlet.http.Part rather than Spring's MultipartFile. The downstream classifier still consumes the stirling.software.common.model.MultipartFile abstraction (size + content-type + input stream). This constructor adapts a Part into that abstraction so both the untouched interceptor and the classifier ...
- `app/saas/src/main/java/stirling/software/saas/payg/entitlement/EntitlementGuard.java:64` - pipeline must never block a customer because the guard tripped on a transient DB error. was a Spring {@code @Component} implementing {@code HandlerInterceptor}. Convert to a JAX-RS {@code @Provider} ContainerRequestFilter (priority {@code PaygWebMvcConfig.ENTITLEMENT_GUARD_ORDER}). Handler-annotation introspection now uses a reflective {@link Method} fallback; HTTP status/header/media-type constants are inlined literals.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:69` - and counted on {@code payg.filter.errors}. The customer's tool call always proceeds. was a Spring {@code @Component} ({@code @Profile("saas")}) implementing {@code AsyncHandlerInterceptor}. Convert to a JAX-RS {@code @Provider} request/response filter pair. Handler-annotation introspection now uses a reflective {@link Method} fallback (see {@link #resolveResourceMethod}); multipart access uses the servlet-native {@link Part} API ...
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:91` - literal value of the former Spring constant {@code HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE}. Replace with the JAX-RS route template obtained from {@code @Context UriInfo} / {@code ResourceInfo} during the filter conversion.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:181` - was @Override AsyncHandlerInterceptor#preHandle(request, response, handler). Convert to a JAX-RS ContainerRequestFilter.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:242` - was `request instanceof MultipartHttpServletRequest mreq` + mreq.getMultiFileMap(). Now uses servlet-native request.getParts(). A non-multipart request yields no file parts and short-circuits, preserving the original behavior.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:332` - the {@link JobInput} record's first component is still Spring's {@code MultipartFile} (owned by another module). This interceptor now sources inputs from the servlet {@link Part} API. Once {@code JobInput} is migrated to carry a {@link Part} (or a neutral size+content-type holder), construct it directly here: {@code return new JobInput(part, path);}. Kept as a single adaptation seam so the rest of the charge flow is untouched.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:343` - was @Override AsyncHandlerInterceptor#afterCompletion(request, response, handler, Exception). Convert to a JAX-RS ContainerResponseFilter.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygChargeInterceptor.java:488` - was @Override AsyncHandlerInterceptor#afterConcurrentHandlingStarted. JAX-RS handles async dispatch differently; no direct equivalent required.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygFilterProperties.java:24` - @ConfigurationProperties(prefix="payg.filter"); bind via @ConfigProperty or @ConfigMapping
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygResponseBodyWrapperFilter.java:33` - this was a Spring {@code OncePerRequestFilter} ({@code @Component @Profile("saas")}). It must be re-registered as a {@code jakarta.servlet.Filter} (or a JAX-RS {@code @jakarta.ws.rs.ext.Provider} ContainerResponse filter pair) and ordered ahead of the PAYG interceptor so the response wrapper is available in afterCompletion. The Spring base class provided once-per-request dispatch and the {@code doFilterInternal} hook; that ...
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygResponseBodyWrapperFilter.java:61` - was @Override of Spring OncePerRequestFilter#doFilterInternal. Retains the servlet signature; invoke from the filter registration's doFilter once converted.
- `app/saas/src/main/java/stirling/software/saas/payg/filter/PaygWebMvcConfig.java:13` - Holds the PAYG hot-path ordering constants. Under Spring MVC these registered {@link PaygChargeInterceptor} and the entitlement guard as ordered interceptors; under Quarkus the interceptor/guard are JAX-RS filters that self-order via {@code @Priority}. The order constants remain the single source of truth for that relative ordering. the Spring {@code WebMvcConfigurer#addInterceptors} registration was removed. Re-express it as ...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:55` - Stateless JWT authentication filter for the saas profile. this was a Spring {@code OncePerRequestFilter}. It must be re-registered as a JAX-RS {@code @jakarta.ws.rs.container.ContainerRequestFilter} with {@code @jakarta.ws.rs.ext.Provider} (or a {@code jakarta.servlet.Filter}) and ordered before the Quarkus OIDC/auth processing. The {@code doFilterInternal}/{@code shouldNotFilter} servlet signatures are retained here; the ...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:72` - placeholder for Spring's {@code org.springframework.security.oauth2.jwt.JwtDecoder}. Replace with Quarkus OIDC token parsing that yields a verified {@link JsonWebToken} (or throws on invalid token).
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:88` - the Spring AuthenticationEntryPoint (BearerTokenAuthenticationEntryPoint) that wrote the 401 challenge has no Quarkus equivalent here. When converting to a JAX-RS @Provider filter, emit the 401 / WWW-Authenticate response directly (or delegate to Quarkus OIDC) in place of authenticationEntryPoint.commence(...).
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:108` - this retains the original OncePerRequestFilter.doFilterInternal behavior. Wire it into a JAX-RS ContainerRequestFilter / servlet Filter. The error branch previously called authenticationEntryPoint.commence(request, response, e); emit the 401 response directly during that conversion.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:143` - was authenticationEntryPoint.commence(request, response, e) (Spring BearerTokenAuthenticationEntryPoint). Emit the 401 challenge response here when converting to a JAX-RS @Provider filter.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:219` - previously caught Spring's JwtException and rethrew InvalidBearerTokenException("Invalid JWT", e). Adjust to the exception type thrown by the Quarkus OIDC token parser.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:313` - was Spring's DataIntegrityViolationException (email-collision race). jakarta.persistence.PersistenceException is broader; narrow to the Hibernate/JPA constraint-violation type once the persistence layer is finalized.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:409` - Concurrent creation; fall through, the row exists. was Spring's DataIntegrityViolationException. Narrow to the Hibernate/JPA constraint-violation type once the persistence layer is finalized.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:424` - Parallel filter won the race; fetch the winning row. was Spring's DataIntegrityViolationException. Narrow to the Hibernate/JPA constraint-violation type once the persistence layer is finalized.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:457` - ApiKeyAuthenticationToken is a plain POJO that does not implement the Authentication shim. Wrap the principal/credentials/authorities in a UsernamePasswordAuthenticationToken (which does) so it can be set on the SecurityContext. Re-wire to a Quarkus SecurityIdentity when the API-key auth path is migrated.
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseAuthenticationFilter.java:483` - --------------------------------------------------------------------------------------------- claim accessor adapters. Spring's Jwt exposed typed claim getters (getClaimAsString/getClaimAsStringList/getClaimAsInstant/getClaimAsBoolean). MicroProfile JsonWebToken only exposes a generic getClaim(name); these helpers reproduce the original typed semantics so the validation/user-creation logic is preserved unchanged ...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseSecurityConfig.java:38` - Stateless Supabase-JWT security chain. this class was a Spring {@code @Configuration} with {@code @EnableWebSecurity}, {@code @EnableMethodSecurity}, {@code @Profile("saas")} and {@code @Order(1)}. The {@code SecurityFilterChain} bean (CSRF/CORS/session/oauth2ResourceServer wiring) has no Quarkus equivalent and must be re-expressed declaratively via {@code quarkus.http.auth.*} config plus Quarkus OIDC/SmallRye-JWT. The {@code ...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseSecurityConfig.java:72` - the original @Bean SecurityFilterChain saasSecurityFilterChain(...) configured CSRF-disabled, CORS, STATELESS sessions, permitAll matchers for OPTIONS/actuator-health/config/static/public-auth/frontend routes, anyRequest().authenticated(), registered SupabaseAuthenticationFilter before BearerTokenAuthenticationFilter, set a BearerTokenAuthenticationEntryPoint + BearerTokenAccessDeniedHandler, and wired ...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseSecurityConfig.java:168` - original @Bean CorsConfigurationSource configured CORS for the Spring SecurityFilterChain (allowed origins/methods/headers, exposed header WWW-Authenticate, allowCredentials=true, maxAge=3600). Re-express via quarkus.http.cors.* properties. The origin-resolution logic (operator override vs. defaults, the Tauri desktop origins, and the wildcard warning) is retained below as a helper for that translation.
</details>
<details><summary><b>Spring Security -> quarkus-oidc / SecurityIdentity</b> (91)</summary>
- `app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesSaml2ResourceTest.java:15` - Spring Boot test framework not available in Quarkus
- `app/proprietary/build.gradle:44` - ---- SAML2: no native Quarkus extension. Rehosted on OpenSAML 5 (already pinned via openSamlVersion) following the dnulnets/quarkus-saml example. spring-security-saml2- service-provider and spring-security-core are removed; the SAML wiring is reimplemented on a Jakarta servlet + OpenSAML 5 (quarkus-undertow provides the servlet runtime). TODO: Migration required - reimplement Saml2Configuration / CustomSaml2* on OpenSAML 5. ----
- `app/proprietary/src/main/java/stirling/software/proprietary/config/AsyncConfig.java:54` - TODO: Migration required - this previously wrapped the executor in Spring Security's DelegatingSecurityContextExecutor to propagate the SecurityContext onto background threads. Quarkus has no direct equivalent; the SecurityIdentity must be captured on the caller thread and re-established on the worker thread (e.g. via a captured io.quarkus.security.identity.SecurityIdentity or org.eclipse.microprofile.context.ThreadContext from MicroProfile Context Propagation). For now only MDC context is pr...
- `app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java:447` - TODO: Migration required - Spring distinguished UserDetails / OAuth2User / CustomSaml2AuthenticatedPrincipal off authentication.getPrincipal() to set the oAuth2Login / saml2Login flags. Under Quarkus the auth mechanism is exposed via SecurityIdentity attributes (e.g. quarkus-oidc IdToken / SAML augmentor). Until OAuth2/ SAML are wired to quarkus-oidc, only the username is resolved and the login-type flags default to false.
- `app/proprietary/src/main/java/stirling/software/proprietary/controller/api/SignatureController.java:36` - Controller for managing user signatures in proprietary/authenticated mode only. Requires user authentication and enforces per-user storage limits. TODO: Migration required - the original endpoints were guarded by Spring Security SpEL expressions ({@code @PreAuthorize("isAuthenticated() && !hasAuthority('ROLE_DEMO_USER')")} and {@code @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")}). These are not simple role checks, so they cannot be expressed with {@code @RolesAllowed}. Authentication shou...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/McpServerController.java:229` - TODO: Migration required - the Spring code derived scopes from GrantedAuthority values prefixed with "SCOPE_". Quarkus SecurityIdentity.getRoles() typically already carries the bare role/scope names (quarkus-oidc maps OIDC scopes to roles without the SCOPE_ prefix). Confirm the configured quarkus.oidc role/scope mapping; if scopes arrive as a "scope" claim, read them via securityIdentity.getAttribute("scope")/getClaims() instead. For now we accept both the bare role and any "SCOPE_"-prefixed ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:56` - TODO: Migration required - replace Spring exception type checks below (DisabledException, LockedException, BadCredentialsException, UsernameNotFoundException, InternalAuthenticationServiceException) with the Quarkus authentication-failure type(s), and replace each getRedirectStrategy().sendRedirect(request, response, "...") call with a Quarkus redirect (e.g. response.sendRedirect(...) or building a 302 jakarta.ws.rs.core.Response from the auth mechanism).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:66` - TODO: Migration required - sendRedirect("/logout?userIsDisabled=true")
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:74` - TODO: Migration required - sendRedirect("/login?error=locked")
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:88` - TODO: Migration required - sendRedirect("/login?error=locked")
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:93` - TODO: Migration required - sendRedirect("/login?error=badCredentials")
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:98` - TODO: Migration required - sendRedirect("/login?error=oauth2AuthenticationError")
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:102` - TODO: Migration required - default failure handling previously delegated to SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure (redirect to the configured failure URL).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:107` - TODO: Migration required - these predicates stand in for Spring Security's exception type hierarchy and must be rewired to the Quarkus authentication-failure type(s) once the auth mechanism is chosen.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java:58` - TODO: Migration required - signature changed from Spring's onAuthenticationSuccess(HttpServletRequest, HttpServletResponse, org.springframework.security.core.Authentication). The Spring Authentication parameter has been dropped here; JwtServiceInterface#generateToken(Authentication, ...) still requires it (JwtServiceInterface is a separate file that must be migrated to accept a Quarkus SecurityIdentity / principal). For now the username is read from the request parameter as before; wire the a...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java:78` - TODO: Migration required - JwtServiceInterface#generateToken expected a Spring Authentication. Pass the migrated Quarkus identity once JwtServiceInterface is ported; generating the token by username for now.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java:112` - TODO: Migration required - placeholder for reading the redirect URL off whatever object the migrated request cache stores. The Spring SavedRequest#getRedirectUrl() is gone.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:131` - TODO: Migration required - the following Spring-Security collaborators were injected as @Autowired(required=false) optional beans and consumed only inside the removed HttpSecurity DSL (GrantedAuthoritiesMapper, RelyingPartyRegistrationRepository, OpenSaml5AuthenticationRequestResolver, ClientRegistrationRepository, PasswordEncoder). They are dropped here because their types are Spring-Security-only; reintroduce equivalents (quarkus-oidc client config, OpenSAML 5 SP wiring, a CDI password hash...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AuthController.java:280` - TODO: Migration required - was SecurityContextHolder.getContext().getAuthentication(). Quarkus SecurityIdentity has no Spring UserDetails principal; loading the full User here requires a SecurityIdentityAugmentor that attaches the User (or re-loading via userDetailsService by name). Until then we re-load the user from the identity name.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/identity/UserSecurityIdentityAugmentor.java:25` - Attaches the {@link User} entity as the {@link SecurityIdentity} principal for any authenticated request. Spring exposed the {@code User} directly via {@code Authentication#getPrincipal()} (it implemented {@code UserDetails}), so a lot of the code base does {@code principal instanceof User} (folders, file storage, sessions, audit, UserController). This augmentor restores that for the Quarkus auth paths (JWT Bearer, X-API-KEY, and later OIDC/SAML): it re-loads the user by name and rebuilds the...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/model/Authority.java:20` - TODO: Migration required - this entity previously implemented Spring Security's org.springframework.security.core.GrantedAuthority. That interface only required String getAuthority(), which the Lombok @Getter on the 'authority' field still provides. Quarkus uses its own role model (SecurityIdentity roles); when wiring the IdentityProvider that loads users, map this 'authority' value into the granted roles.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java:40` - TODO: Migration required - this entity previously implemented org.springframework.security.core.userdetails.UserDetails. Quarkus has no UserDetails contract; the user-loading/principal adaptation must be rehosted in a Quarkus IdentityProvider (or SecurityIdentityAugmentor) that builds a SecurityIdentity from this entity. The Lombok getters still expose getUsername()/getPassword()/getAuthorities()/ isEnabled() so that adapter can read them directly. isEnabled() override below is retained as pl...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/model/exception/AuthenticationFailureException.java:3` - TODO: Migration required - originally extended org.springframework.security.core.AuthenticationException (Spring Security). Quarkus has no direct equivalent base type; extend RuntimeException so this remains a usable application exception. If integrated with quarkus-security, consider mapping to io.quarkus.security.AuthenticationFailedException.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:33` - TODO: Migration required - this class extended Spring Security's SavedRequestAwareAuthenticationSuccessHandler, which has no Quarkus equivalent. Under quarkus-oidc there is no AuthenticationSuccessHandler concept; the post-login OAuth2 success flow must be rehosted, e.g. via a SecurityIdentityAugmentor plus a JAX-RS callback resource (or a jakarta.servlet endpoint) that performs the redirect/JWT-issuance below. The Spring Authentication/OAuth2User/OAuth2AuthenticationToken/SavedRequest types ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:54` - TODO: Migration required - the original signature took a Spring Security org.springframework.security.core.Authentication. Under quarkus-oidc this should receive an io.quarkus.security.identity.SecurityIdentity (or the OIDC IdToken/UserInfo). The "authentication" parameter is now typed as Object so the body still compiles; replace it with the real quarkus-oidc principal type and re-implement principal extraction below when wiring the success flow.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:67` - TODO: Migration required - principal extraction relied on Spring Security OAuth2User / UserDetails. Derive the username from the quarkus-oidc principal (SecurityIdentity / IdToken claims) instead.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:100` - TODO: Migration required - SavedRequest / "SPRING_SECURITY_SAVED_REQUEST" is a Spring Security web construct. Under quarkus-oidc the original target URL is preserved via the OIDC state/restore-path mechanism (quarkus.oidc.authentication.restore-path-after-redirect) rather than a session attribute. Re-implement saved-request resolution accordingly; the session attribute read below is left as a placeholder and will currently be null.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:112` - TODO: Migration required - originally delegated to SavedRequestAwareAuthenticationSuccessHandler.onAuthenticationSuccess to redirect to the saved request. Reimplement the redirect to the saved/original destination here once the quarkus-oidc saved-request mechanism is in place.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:122` - TODO: Migration required - originally threw Spring Security's org.springframework.security.authentication.LockedException. Replace with the exception type the quarkus-oidc success flow expects (or a redirect to a locked page); throwing a plain IllegalStateException here as a placeholder.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:130` - TODO: Migration required - originally used Spring's RedirectStrategy via getRedirectStrategy().sendRedirect(...). Using the servlet response directly.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:154` - TODO: Migration required - SSO provider/claims extraction relied on Spring Security's OAuth2User attributes and OAuth2AuthenticationToken. Re-derive the OIDC "sub" claim and the provider registration id from the quarkus-oidc principal.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:189` - Web: Use default expiry TODO: Migration required - JwtServiceInterface.generateToken(Authentication, claims) takes a Spring Security Authentication. Until JwtServiceInterface is migrated, issue the token by username (same identity) to avoid the Spring dependency here.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:214` - TODO: Migration required - placeholder for principal -> username extraction. Originally used Spring Security OAuth2User.getName() / UserDetails.getUsername(). Implement against the quarkus-oidc principal (SecurityIdentity.getPrincipal().getName() / IdToken claims).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:219` - "TODO: Migration required - extract username from the quarkus-oidc principal");
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:222` - TODO: Migration required - placeholder for the OIDC "sub" claim. Originally oAuth2User.getAttribute("sub"). Read it from the quarkus-oidc IdToken/UserInfo.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:226` - "TODO: Migration required - extract the 'sub' claim from the quarkus-oidc principal");
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:229` - TODO: Migration required - placeholder for the saved-request redirect URL. Originally SavedRequest.getRedirectUrl().
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:233` - "TODO: Migration required - resolve the saved-request redirect URL under quarkus-oidc");
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:236` - TODO: Migration required - placeholder for delegating to the saved-request redirect. Originally SavedRequestAwareAuthenticationSuccessHandler.onAuthenticationSuccess(...).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:242` - "TODO: Migration required - redirect to the saved/original destination under quarkus-oidc");
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:252` - TODO: Migration required - originally cast to Spring Security's OAuth2AuthenticationToken and called getAuthorizedClientRegistrationId(). Derive the OIDC provider/tenant id from the quarkus-oidc principal instead.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:388` - TODO: Migration required - originally built the Set-Cookie value with Spring's org.springframework.http.ResponseCookie. Replaced with a manually built RFC 6265 Set-Cookie string to drop the Spring HTTP dependency. Consider switching to jakarta.servlet.http.Cookie / response.addCookie once SameSite handling is confirmed.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:27` - TODO: Migration required - OAuth2 client/login is a Spring Security feature (org.springframework.security.oauth2.client.*) with NO direct Quarkus equivalent. In Quarkus the OIDC/OAuth2 client is configured declaratively via quarkus-oidc (quarkus.oidc.* and named tenants quarkus.oidc.<tenant>.* in application.properties), not by programmatically building a ClientRegistrationRepository. This class previously @Produces'd a ClientRegistrationRepository and a GrantedAuthoritiesMapper. Those produc...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:50` - TODO: Migration required - @Lazy has no Quarkus equivalent; CDI proxies break the original lazy cycle. UserService is injected eagerly. If a genuine lazy/circular dependency exists, switch to jakarta.enterprise.inject.Instance<UserService> and resolve at call time.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:70` - Resolves the set of configured OAuth2 providers from ApplicationProperties and validates each one. The original implementation built a Spring Security ClientRegistrationRepository from these providers. TODO: Migration required - the return type was org.springframework.security.oauth2.client.registration.ClientRegistrationRepository, produced via Spring @Bean. quarkus-oidc does not consume a ClientRegistrationRepository; instead each validated Provider below must be emitted as a named OIDC ten...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:116` - TODO: Migration required - the original built a ClientRegistration via ClientRegistrations.fromIssuerLocation(issuer) (OIDC discovery). Under quarkus-oidc this maps to quarkus.oidc.<name>.auth-server-url=<issuer> with discovery enabled, plus client-id/credentials.secret/authentication.scopes/token-state username attribute.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:139` - TODO: Migration required - the original built a ClientRegistration with explicit authorizationUri/tokenUri/userInfoUri + redirectUri(REDIRECT_URI_PATH + name) + AUTHORIZATION_CODE grant. Under quarkus-oidc this maps to a named tenant quarkus.oidc.google.* (authorization-path/token-path/user-info-path or auth-server-url, authentication.redirect-path, application-type=web-app). Google's endpoints come from the GoogleProvider getters below.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:175` - TODO: Migration required - the original built a ClientRegistration with explicit authorizationUri/tokenUri/userInfoUri + redirectUri(REDIRECT_URI_PATH + name) + AUTHORIZATION_CODE grant. Map to quarkus.oidc.github.* tenant config (GitHub is a plain OAuth2, not OIDC, provider - quarkus-oidc may require provider=github or explicit *-path settings).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:220` - TODO: Migration required - the original built a ClientRegistration via ClientRegistrations.fromIssuerLocation(issuer) (OIDC discovery) with redirectUri(REDIRECT_URI_PATH + name) + AUTHORIZATION_CODE grant. Map to a named tenant quarkus.oidc.<name>.auth-server-url=<issuer> (discovery on), client-id/credentials.secret/authentication.scopes, authentication.redirect-path.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:241` - TODO: Migration required - this was a Spring Security
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java:19` - TODO: Migration required - the original @ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true") gated this class on a runtime property. This is a utility holding only static methods (not a CDI bean), so the annotation was a no-op for instantiation and is dropped. Callers must enforce the security.saml2.enabled runtime toggle (e.g. via a runtime guard at the SAML SP entry point); see the SAML2 migration notes.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java:7` - TODO: Migration required - this record implemented Spring Security's org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal. There is NO Quarkus SAML extension; the SAML SP must be rehosted on a Jakarta @WebServlet using OpenSAML 5 (dnulnets/quarkus-saml pattern). The OpenSAML-derived principal data (name, attributes, nameId, sessionIndexes) is preserved below as a plain data carrier; re-wire it into the replacement SAML authentication flow / SecurityId...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java:23` - TODO: Migration required - there is NO Quarkus SAML extension. This class previously implemented Spring Security's org.springframework.security.core.convert.converter.Converter< OpenSaml5AuthenticationProvider.ResponseToken, Saml2Authentication> to plug into Spring's SAML2 OpenSaml5AuthenticationProvider pipeline. The OpenSAML 5 (org.opensaml.*) assertion/attribute extraction logic below is preserved unchanged. The Spring SAML2 glue has been removed: - org.springframework.security.saml2.provi...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java:83` - TODO: Migration required - signature changed from convert(OpenSaml5AuthenticationProvider.ResponseToken) returning Saml2Authentication. Re-wire the input to the OpenSAML 5 Assertion obtained from the rehosted SAML SP and the output to a Quarkus SecurityIdentity. The OpenSAML attribute/identifier/session-index extraction logic below is the reusable part and is preserved. The returned CustomSaml2AuthenticatedPrincipal plus the resolved role (ROLE_USER or the user's role) carry the data the new ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java:115` - TODO: Migration required - resolved authority was previously wrapped in a Spring SimpleGrantedAuthority("ROLE_USER" / userService.findRole(user)). Map this role String onto a Quarkus SecurityIdentity role when wiring the SAML SP / SecurityIdentityAugmentor.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:13` - TODO: Migration required - this class implemented Spring Security's org.springframework.security.saml2.provider.service.web.Saml2AuthenticationRequestRepository over Saml2PostAuthenticationRequest / RelyingPartyRegistration(Repository). There is NO Quarkus SAML extension, so the Spring Security SAML glue (interface, Saml2PostAuthenticationRequest, RelyingPartyRegistration[Repository]) has been removed. The SAML SP must be rehosted on a Jakarta @WebServlet using OpenSAML 5 (see the dnulnets/qu...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:39` - TODO: Migration required - original signature was saveAuthenticationRequest(Saml2PostAuthenticationRequest authRequest, HttpServletRequest, HttpServletResponse). Pass the OpenSAML-derived claims + relayState once the SP is rehosted.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:66` - TODO: Migration required - original returned Saml2PostAuthenticationRequest. Map the returned claims back to the OpenSAML AuthnRequest model once the SP is rehosted.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:80` - TODO: Migration required - original returned Saml2PostAuthenticationRequest.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:112` - TODO: Migration required - original signature was serializeSamlRequest(Saml2PostAuthenticationRequest authRequest). Build this claims map from the OpenSAML AuthnRequest fields (id, relyingPartyRegistrationId / SP entity id, authenticationRequestUri / destination, samlRequest, relayState) once the SP is rehosted.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:133` - TODO: Migration required - original returned Saml2PostAuthenticationRequest rebuilt via Saml2PostAuthenticationRequest.withRelyingPartyRegistration(...). Resolve the RelyingPartyRegistration equivalent (SP metadata) and rebuild the OpenSAML AuthnRequest from these claims once the SP is rehosted. For now the raw claims map is returned unchanged.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:19` - TODO: Migration required - there is NO Quarkus SAML extension. The original class was a Spring @Configuration that exposed two @Bean factory methods producing Spring Security SAML2 types (org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository and ...web.authentication.OpenSaml5AuthenticationRequestResolver). Those builder/glue types have no Quarkus equivalent, so the Spring Security SAML2 imports and @Configuration/@Bean wiring have been removed. T...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:41` - TODO: Migration required - originally a @Bean returning Spring Security's RelyingPartyRegistrationRepository built via RelyingPartyRegistration.withRegistrationId(...) (InMemoryRelyingPartyRegistrationRepository, Saml2X509Credential, Saml2MessageBinding). Those Spring Security SAML2 builder types are unavailable in Quarkus. The credential loading (CertificateUtils via the common Resource shim) and the entityId / ACS / SLO location strings are kept verbatim so the OpenSAML-5-based SP rehost ca...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:75` - TODO: Migration required - was Saml2X509Credential.verification(idpCert). Re-create the IdP verification credential from idpCert using OpenSAML 5 (BasicX509Credential).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:98` - TODO: Migration required - was new Saml2X509Credential(privateKey, cert, Saml2X509CredentialType.SIGNING). Build the SP signing credential from the key/cert below using OpenSAML 5 (BasicX509Credential) instead of Spring Security's Saml2X509Credential.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:125` - TODO: Migration required - the following Spring Security RelyingPartyRegistration was built here and stored in an InMemoryRelyingPartyRegistrationRepository. Re-implement against the OpenSAML-5-based SP using entityId / acsLocation / sloResponseLocation, the IdP issuer (samlConf.getIdpIssuer()), SSO/SLO bindings (POST) and locations (samlConf.getIdpSingleLoginUrl() / samlConf.getIdpSingleLogoutUrl()), authnRequestsSigned and wantAuthnRequestsSigned both true, and the signing/verification cred...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:142` - TODO: Migration required - originally a @Bean returning Spring Security's OpenSaml5AuthenticationRequestResolver, configured with a RelayState resolver and an AuthnRequest customizer. That resolver type is Spring-Security-specific and has no Quarkus equivalent. The RelayState logic (Tauri detection -> TauriSamlUtils.buildRelayState(nonce)) and the AuthnRequest customization (unique ARQ id + logging) are PRESERVED below as helper methods so the OpenSAML-5-based SP rehost can invoke them when b...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java:24` - TODO: Migration required - SecurityIdentity is request-scoped; injecting it into an @ApplicationScoped bean relies on Quarkus' client proxy resolving the current request's identity. Verify this resolves correctly when invoked outside an active HTTP request (e.g. scheduled/background contexts), where the identity may be anonymous/null.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java:18` - TODO: Migration required - quarkus-oidc has no equivalent of Spring's OAuth2UserService<OidcUserRequest, OidcUser> / OidcUserService delegate. Under quarkus-oidc the OIDC flow is handled by the extension (quarkus.oidc.* config); per-login user mapping and the "useAsUsername" claim selection should be re-implemented in a io.quarkus.security.identity.SecurityIdentityAugmentor (inject the @io.quarkus.oidc.IdToken JsonWebToken / OidcSession), and the blocked-account / hasPassword checks below sho...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java:58` - Resolves and validates the local user for an OIDC login. TODO: Migration required - this method previously implemented Spring's {@code OAuth2UserService<OidcUserRequest, OidcUser>.loadUser}. Under quarkus-oidc there is no user-request object handed to application code; instead call this logic from a {@code SecurityIdentityAugmentor} once quarkus-oidc has produced the {@code SecurityIdentity}. Provide the registration/tenant id, the merged claim map and the ID-token claim map from the augmento...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java:114` - TODO: Migration required - was org.springframework.security.authentication .LockedException; surface this as io.quarkus.security.AuthenticationFailedException (or a custom locked-account exception) from the SecurityIdentityAugmentor.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java:147` - TODO: Migration required - was wrapped as org.springframework.security.oauth2.core.OAuth2AuthenticationException(OAuth2Error); rethrow as io.quarkus.security.AuthenticationFailedException from the augmentor.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java:163` - TODO: Migration required - was OAuth2AuthenticationException("Unexpected error during authentication"); rethrow as io.quarkus.security.AuthenticationFailedException.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java:16` - TODO: Migration required - this class implemented org.springframework.security.core.userdetails.UserDetailsService and returned a org.springframework.security.core.userdetails.UserDetails. Quarkus has no UserDetailsService contract; the user-loading logic below should be invoked from a Quarkus IdentityProvider (or SecurityIdentityAugmentor) that turns the returned User into a SecurityIdentity. The method is retained as a plain service returning the User entity. Former Spring exceptions are ma...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/JwtServiceInterface.java:17` - TODO: Migration required - the implementation must derive the username/claims from SecurityIdentity (getPrincipal()/getRoles()) instead of the former Spring Authentication.getName()/getAuthorities().
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java:684` - TODO: Migration required - SessionPersistentRegistry still exposes Spring Security types (SessionInformation, UserDetails, OAuth2User). Once that collaborator is ported to a Quarkus session store, drop these Spring Security imports and adjust the principal type checks accordingly.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java:8` - TODO: Migration required - SessionRegistryImpl is a Spring Security type (org.springframework.security.core.session.SessionRegistryImpl) with no Quarkus equivalent. Concurrent-session tracking must be rehosted (e.g. a custom bean backed by SessionPersistentRegistry / SecurityIdentity, or quarkus session management). The original producer was: @Bean public SessionRegistryImpl sessionRegistry() { return new SessionRegistryImpl(); }
- `app/proprietary/src/main/java/stirling/software/proprietary/security/supabase/SupabaseJwtDecoderFactory.java:12` - Produces the JWKS configuration for the proprietary Supabase login path. Only relevant when {@code security.supabase.user-login.enabled=true}. TODO: Migration required - this class previously produced a Spring Security {@code org.springframework.security.oauth2.jwt.JwtDecoder} bean (Nimbus-based) via {@code @Configuration}/{@code @Bean}, conditionally registered with {@code @ConditionalOnProperty(security.supabase.user-login.enabled=true)}. Quarkus has no {@code JwtDecoder} abstraction; beare...
- `app/proprietary/src/main/java/stirling/software/proprietary/service/AuditService.java:999` - Quarkus migration: was SecurityContextHolder.getContext().getAuthentication(). TODO: Migration required - the original code distinguished API-key auth from web/JWT auth via `instanceof ApiKeyAuthenticationToken`. Under Quarkus the runtime principal is io.quarkus.security.identity.SecurityIdentity and ApiKeyAuthenticationToken has been reduced to a plain POJO (it is no longer the identity type), so the API-key vs WEB distinction can no longer be made by instanceof here. Once the API-key auth p...
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:74` - TODO: Migration required - SecurityIdentity replaces Spring's Authentication. The collaborator FileStorageService still exposes canAccessShareLink(FileShare, org.springframework.security .core.Authentication) and recordShareAccess(FileShare, Authentication, boolean). Once that service is migrated those methods should accept SecurityIdentity (or io.quarkus.security SecurityContext) and this injected identity can be passed through directly.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:271` - TODO: Migration required - canAccessShareLink/recordShareAccess still take Spring Authentication. Passing null preserves the anonymous-deny behavior until the service is migrated to SecurityIdentity; once migrated, pass `securityIdentity` through instead.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:296` - TODO: Migration required - canAccessShareLink still takes Spring Authentication; pass `securityIdentity` once FileStorageService is migrated.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:380` - TODO: Migration required - Spring's Authentication-based anonymous check is replaced by SecurityIdentity. Verify "anonymous" semantics match once the security layer is migrated.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/service/FolderService.java:435` - TODO: Migration required - a Quarkus SecurityIdentityAugmentor/IdentityProvider must attach the stirling.software.proprietary.security.model.User entity as the SecurityIdentity principal (Spring exposed it directly via Authentication#getPrincipal, since User used to implement UserDetails). Until that augmentor exists, this only resolves when the principal IS the User entity; otherwise it rejects as 401 rather than guessing at a username->User lookup.
- `app/proprietary/build.gradle:44` - ---- SAML2: no native Quarkus extension. Rehosted on OpenSAML 5 (already pinned via openSamlVersion) following the dnulnets/quarkus-saml example. spring-security-saml2- service-provider and spring-security-core are removed; the SAML wiring is reimplemented on a Jakarta servlet + OpenSAML 5 (quarkus-undertow provides the servlet runtime). reimplement Saml2Configuration / CustomSaml2* on OpenSAML 5. ----
- `app/proprietary/src/main/java/stirling/software/proprietary/config/AsyncConfig.java:54` - this previously wrapped the executor in Spring Security's DelegatingSecurityContextExecutor to propagate the SecurityContext onto background threads. Quarkus has no direct equivalent; the SecurityIdentity must be captured on the caller thread and re-established on the worker thread (e.g. via a captured io.quarkus.security.identity.SecurityIdentity or org.eclipse.microprofile.context.ThreadContext from MicroProfile Context ...
- `app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java:447` - Spring distinguished UserDetails / OAuth2User / CustomSaml2AuthenticatedPrincipal off authentication.getPrincipal() to set the oAuth2Login / saml2Login flags. Under Quarkus the auth mechanism is exposed via SecurityIdentity attributes (e.g. quarkus-oidc IdToken / SAML augmentor). Until OAuth2/ SAML are wired to quarkus-oidc, only the username is resolved and the login-type flags default to false.
- `app/proprietary/src/main/java/stirling/software/proprietary/controller/api/SignatureController.java:36` - Controller for managing user signatures in proprietary/authenticated mode only. Requires user authentication and enforces per-user storage limits. the original endpoints were guarded by Spring Security SpEL expressions ({@code @PreAuthorize("isAuthenticated() && !hasAuthority('ROLE_DEMO_USER')")} and {@code @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")}). These are not simple role checks, so they cannot be expressed with ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/McpServerController.java:229` - the Spring code derived scopes from GrantedAuthority values prefixed with "SCOPE_". Quarkus SecurityIdentity.getRoles() typically already carries the bare role/scope names (quarkus-oidc maps OIDC scopes to roles without the SCOPE_ prefix). Confirm the configured quarkus.oidc role/scope mapping; if scopes arrive as a "scope" claim, read them via securityIdentity.getAttribute("scope")/getClaims() instead. For now we accept both ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:56` - replace Spring exception type checks below (DisabledException, LockedException, BadCredentialsException, UsernameNotFoundException, InternalAuthenticationServiceException) with the Quarkus authentication-failure type(s), and replace each getRedirectStrategy().sendRedirect(request, response, "...") call with a Quarkus redirect (e.g. response.sendRedirect(...) or building a 302 jakarta.ws.rs.core.Response from the auth mechanism).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:66` - sendRedirect("/logout?userIsDisabled=true")
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:74` - sendRedirect("/login?error=locked")
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:88` - sendRedirect("/login?error=locked")
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:93` - sendRedirect("/login?error=badCredentials")
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:98` - sendRedirect("/login?error=oauth2AuthenticationError")
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:102` - default failure handling previously delegated to SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure (redirect to the configured failure URL).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java:107` - these predicates stand in for Spring Security's exception type hierarchy and must be rewired to the Quarkus authentication-failure type(s) once the auth mechanism is chosen.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java:58` - signature changed from Spring's onAuthenticationSuccess(HttpServletRequest, HttpServletResponse, org.springframework.security.core.Authentication). The Spring Authentication parameter has been dropped here; JwtServiceInterface#generateToken(Authentication, ...) still requires it (JwtServiceInterface is a separate file that must be migrated to accept a Quarkus SecurityIdentity / principal). For now the username is read from the ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java:78` - JwtServiceInterface#generateToken expected a Spring Authentication. Pass the migrated Quarkus identity once JwtServiceInterface is ported; generating the token by username for now.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java:112` - placeholder for reading the redirect URL off whatever object the migrated request cache stores. The Spring SavedRequest#getRedirectUrl() is gone.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:131` - the following Spring-Security collaborators were injected as @Autowired(required=false) optional beans and consumed only inside the removed HttpSecurity DSL (GrantedAuthoritiesMapper, RelyingPartyRegistrationRepository, OpenSaml5AuthenticationRequestResolver, ClientRegistrationRepository, PasswordEncoder). They are dropped here because their types are Spring-Security-only; reintroduce equivalents (quarkus-oidc client config ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AuthController.java:280` - was SecurityContextHolder.getContext().getAuthentication(). Quarkus SecurityIdentity has no Spring UserDetails principal; loading the full User here requires a SecurityIdentityAugmentor that attaches the User (or re-loading via userDetailsService by name). Until then we re-load the user from the identity name.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/identity/UserSecurityIdentityAugmentor.java:25` - Attaches the {@link User} entity as the {@link SecurityIdentity} principal for any authenticated request. Spring exposed the {@code User} directly via {@code Authentication#getPrincipal()} (it implemented {@code UserDetails}), so a lot of the code base does {@code principal instanceof User} (folders, file storage, sessions, audit, UserController). This augmentor restores that for the Quarkus auth paths (JWT Bearer, X-API-KEY, and later OIDC/SAML): it ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/model/Authority.java:20` - this entity previously implemented Spring Security's org.springframework.security.core.GrantedAuthority. That interface only required String getAuthority(), which the Lombok @Getter on the 'authority' field still provides. Quarkus uses its own role model (SecurityIdentity roles); when wiring the IdentityProvider that loads users, map this 'authority' value into the granted roles.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java:40` - this entity previously implemented org.springframework.security.core.userdetails.UserDetails. Quarkus has no UserDetails contract; the user-loading/principal adaptation must be rehosted in a Quarkus IdentityProvider (or SecurityIdentityAugmentor) that builds a SecurityIdentity from this entity. The Lombok getters still expose getUsername()/getPassword()/getAuthorities()/ isEnabled() so that adapter can read them directly ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/model/exception/AuthenticationFailureException.java:3` - originally extended org.springframework.security.core.AuthenticationException (Spring Security). Quarkus has no direct equivalent base type; extend RuntimeException so this remains a usable application exception. If integrated with quarkus-security, consider mapping to io.quarkus.security.AuthenticationFailedException.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:33` - this class extended Spring Security's SavedRequestAwareAuthenticationSuccessHandler, which has no Quarkus equivalent. Under quarkus-oidc there is no AuthenticationSuccessHandler concept; the post-login OAuth2 success flow must be rehosted, e.g. via a SecurityIdentityAugmentor plus a JAX-RS callback resource (or a jakarta.servlet endpoint) that performs the redirect/JWT-issuance below. The Spring ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:54` - the original signature took a Spring Security org.springframework.security.core.Authentication. Under quarkus-oidc this should receive an io.quarkus.security.identity.SecurityIdentity (or the OIDC IdToken/UserInfo). The "authentication" parameter is now typed as Object so the body still compiles; replace it with the real quarkus-oidc principal type and re-implement principal extraction below when wiring the success flow.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:67` - principal extraction relied on Spring Security OAuth2User / UserDetails. Derive the username from the quarkus-oidc principal (SecurityIdentity / IdToken claims) instead.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:100` - SavedRequest / "SPRING_SECURITY_SAVED_REQUEST" is a Spring Security web construct. Under quarkus-oidc the original target URL is preserved via the OIDC state/restore-path mechanism (quarkus.oidc.authentication.restore-path-after-redirect) rather than a session attribute. Re-implement saved-request resolution accordingly; the session attribute read below is left as a placeholder and will currently be null.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:112` - originally delegated to SavedRequestAwareAuthenticationSuccessHandler.onAuthenticationSuccess to redirect to the saved request. Reimplement the redirect to the saved/original destination here once the quarkus-oidc saved-request mechanism is in place.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:122` - originally threw Spring Security's org.springframework.security.authentication.LockedException. Replace with the exception type the quarkus-oidc success flow expects (or a redirect to a locked page); throwing a plain IllegalStateException here as a placeholder.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:130` - originally used Spring's RedirectStrategy via getRedirectStrategy().sendRedirect(...). Using the servlet response directly.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:154` - SSO provider/claims extraction relied on Spring Security's OAuth2User attributes and OAuth2AuthenticationToken. Re-derive the OIDC "sub" claim and the provider registration id from the quarkus-oidc principal.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:189` - Web: Use default expiry JwtServiceInterface.generateToken(Authentication, claims) takes a Spring Security Authentication. Until JwtServiceInterface is migrated, issue the token by username (same identity) to avoid the Spring dependency here.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:214` - placeholder for principal -> username extraction. Originally used Spring Security OAuth2User.getName() / UserDetails.getUsername(). Implement against the quarkus-oidc principal (SecurityIdentity.getPrincipal().getName() / IdToken claims).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:219` - "extract username from the quarkus-oidc principal");
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:222` - placeholder for the OIDC "sub" claim. Originally oAuth2User.getAttribute("sub"). Read it from the quarkus-oidc IdToken/UserInfo.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:226` - "extract the 'sub' claim from the quarkus-oidc principal");
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:229` - placeholder for the saved-request redirect URL. Originally SavedRequest.getRedirectUrl().
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:233` - "resolve the saved-request redirect URL under quarkus-oidc");
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:236` - placeholder for delegating to the saved-request redirect. Originally SavedRequestAwareAuthenticationSuccessHandler.onAuthenticationSuccess(...).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:242` - "redirect to the saved/original destination under quarkus-oidc");
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:252` - originally cast to Spring Security's OAuth2AuthenticationToken and called getAuthorizedClientRegistrationId(). Derive the OIDC provider/tenant id from the quarkus-oidc principal instead.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java:388` - originally built the Set-Cookie value with Spring's org.springframework.http.ResponseCookie. Replaced with a manually built RFC 6265 Set-Cookie string to drop the Spring HTTP dependency. Consider switching to jakarta.servlet.http.Cookie / response.addCookie once SameSite handling is confirmed.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:27` - OAuth2 client/login is a Spring Security feature (org.springframework.security.oauth2.client.*) with NO direct Quarkus equivalent. In Quarkus the OIDC/OAuth2 client is configured declaratively via quarkus-oidc (quarkus.oidc.* and named tenants quarkus.oidc.<tenant>.* in application.properties), not by programmatically building a ClientRegistrationRepository. This class previously @Produces'd a ClientRegistrationRepository and a ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:50` - @Lazy has no Quarkus equivalent; CDI proxies break the original lazy cycle. UserService is injected eagerly. If a genuine lazy/circular dependency exists, switch to jakarta.enterprise.inject.Instance<UserService> and resolve at call time.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:70` - Resolves the set of configured OAuth2 providers from ApplicationProperties and validates each one. The original implementation built a Spring Security ClientRegistrationRepository from these providers. the return type was org.springframework.security.oauth2.client.registration.ClientRegistrationRepository, produced via Spring @Bean. quarkus-oidc does not consume a ClientRegistrationRepository; instead each validated Provider ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:116` - the original built a ClientRegistration via ClientRegistrations.fromIssuerLocation(issuer) (OIDC discovery). Under quarkus-oidc this maps to quarkus.oidc.<name>.auth-server-url=<issuer> with discovery enabled, plus client-id/credentials.secret/authentication.scopes/token-state username attribute.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:139` - the original built a ClientRegistration with explicit authorizationUri/tokenUri/userInfoUri + redirectUri(REDIRECT_URI_PATH + name) + AUTHORIZATION_CODE grant. Under quarkus-oidc this maps to a named tenant quarkus.oidc.google.* (authorization-path/token-path/user-info-path or auth-server-url, authentication.redirect-path, application-type=web-app). Google's endpoints come from the GoogleProvider getters below.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:175` - the original built a ClientRegistration with explicit authorizationUri/tokenUri/userInfoUri + redirectUri(REDIRECT_URI_PATH + name) + AUTHORIZATION_CODE grant. Map to quarkus.oidc.github.* tenant config (GitHub is a plain OAuth2, not OIDC, provider - quarkus-oidc may require provider=github or explicit *-path settings).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:220` - the original built a ClientRegistration via ClientRegistrations.fromIssuerLocation(issuer) (OIDC discovery) with redirectUri(REDIRECT_URI_PATH + name) + AUTHORIZATION_CODE grant. Map to a named tenant quarkus.oidc.<name>.auth-server-url=<issuer> (discovery on), client-id/credentials.secret/authentication.scopes, authentication.redirect-path.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java:241` - this was a Spring Security
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java:19` - the original @ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true") gated this class on a runtime property. This is a utility holding only static methods (not a CDI bean), so the annotation was a no-op for instantiation and is dropped. Callers must enforce the security.saml2.enabled runtime toggle (e.g. via a runtime guard at the SAML SP entry point); see the SAML2 migration notes.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java:7` - this record implemented Spring Security's org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal. There is NO Quarkus SAML extension; the SAML SP must be rehosted on a Jakarta @WebServlet using OpenSAML 5 (dnulnets/quarkus-saml pattern). The OpenSAML-derived principal data (name, attributes, nameId, sessionIndexes) is preserved below as a plain data carrier; re-wire it into the replacement ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java:23` - there is NO Quarkus SAML extension. This class previously implemented Spring Security's org.springframework.security.core.convert.converter.Converter< OpenSaml5AuthenticationProvider.ResponseToken, Saml2Authentication> to plug into Spring's SAML2 OpenSaml5AuthenticationProvider pipeline. The OpenSAML 5 (org.opensaml.*) assertion/attribute extraction logic below is preserved unchanged. The Spring SAML2 glue has been removed: - ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java:83` - signature changed from convert(OpenSaml5AuthenticationProvider.ResponseToken) returning Saml2Authentication. Re-wire the input to the OpenSAML 5 Assertion obtained from the rehosted SAML SP and the output to a Quarkus SecurityIdentity. The OpenSAML attribute/identifier/session-index extraction logic below is the reusable part and is preserved. The returned CustomSaml2AuthenticatedPrincipal plus the resolved role (ROLE_USER or ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java:115` - resolved authority was previously wrapped in a Spring SimpleGrantedAuthority("ROLE_USER" / userService.findRole(user)). Map this role String onto a Quarkus SecurityIdentity role when wiring the SAML SP / SecurityIdentityAugmentor.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:13` - this class implemented Spring Security's org.springframework.security.saml2.provider.service.web.Saml2AuthenticationRequestRepository over Saml2PostAuthenticationRequest / RelyingPartyRegistration(Repository). There is NO Quarkus SAML extension, so the Spring Security SAML glue (interface, Saml2PostAuthenticationRequest, RelyingPartyRegistration[Repository]) has been removed. The SAML SP must be rehosted on a Jakarta @WebServlet ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:39` - original signature was saveAuthenticationRequest(Saml2PostAuthenticationRequest authRequest, HttpServletRequest, HttpServletResponse). Pass the OpenSAML-derived claims + relayState once the SP is rehosted.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:66` - original returned Saml2PostAuthenticationRequest. Map the returned claims back to the OpenSAML AuthnRequest model once the SP is rehosted.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:80` - original returned Saml2PostAuthenticationRequest.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:112` - original signature was serializeSamlRequest(Saml2PostAuthenticationRequest authRequest). Build this claims map from the OpenSAML AuthnRequest fields (id, relyingPartyRegistrationId / SP entity id, authenticationRequestUri / destination, samlRequest, relayState) once the SP is rehosted.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/JwtSaml2AuthenticationRequestRepository.java:133` - original returned Saml2PostAuthenticationRequest rebuilt via Saml2PostAuthenticationRequest.withRelyingPartyRegistration(...). Resolve the RelyingPartyRegistration equivalent (SP metadata) and rebuild the OpenSAML AuthnRequest from these claims once the SP is rehosted. For now the raw claims map is returned unchanged.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:19` - there is NO Quarkus SAML extension. The original class was a Spring @Configuration that exposed two @Bean factory methods producing Spring Security SAML2 types (org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository and ...web.authentication.OpenSaml5AuthenticationRequestResolver). Those builder/glue types have no Quarkus equivalent, so the Spring Security SAML2 imports and ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:41` - originally a @Bean returning Spring Security's RelyingPartyRegistrationRepository built via RelyingPartyRegistration.withRegistrationId(...) (InMemoryRelyingPartyRegistrationRepository, Saml2X509Credential, Saml2MessageBinding). Those Spring Security SAML2 builder types are unavailable in Quarkus. The credential loading (CertificateUtils via the common Resource shim) and the entityId / ACS / SLO location strings are kept ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:75` - was Saml2X509Credential.verification(idpCert). Re-create the IdP verification credential from idpCert using OpenSAML 5 (BasicX509Credential).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:98` - was new Saml2X509Credential(privateKey, cert, Saml2X509CredentialType.SIGNING). Build the SP signing credential from the key/cert below using OpenSAML 5 (BasicX509Credential) instead of Spring Security's Saml2X509Credential.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:125` - the following Spring Security RelyingPartyRegistration was built here and stored in an InMemoryRelyingPartyRegistrationRepository. Re-implement against the OpenSAML-5-based SP using entityId / acsLocation / sloResponseLocation, the IdP issuer (samlConf.getIdpIssuer()), SSO/SLO bindings (POST) and locations (samlConf.getIdpSingleLoginUrl() / samlConf.getIdpSingleLogoutUrl()), authnRequestsSigned and wantAuthnRequestsSigned both ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/Saml2Configuration.java:142` - originally a @Bean returning Spring Security's OpenSaml5AuthenticationRequestResolver, configured with a RelayState resolver and an AuthnRequest customizer. That resolver type is Spring-Security-specific and has no Quarkus equivalent. The RelayState logic (Tauri detection -> TauriSamlUtils.buildRelayState(nonce)) and the AuthnRequest customization (unique ARQ id + logging) are PRESERVED below as helper methods so the ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java:24` - SecurityIdentity is request-scoped; injecting it into an @ApplicationScoped bean relies on Quarkus' client proxy resolving the current request's identity. Verify this resolves correctly when invoked outside an active HTTP request (e.g. scheduled/background contexts), where the identity may be anonymous/null.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java:18` - quarkus-oidc has no equivalent of Spring's OAuth2UserService<OidcUserRequest, OidcUser> / OidcUserService delegate. Under quarkus-oidc the OIDC flow is handled by the extension (quarkus.oidc.* config); per-login user mapping and the "useAsUsername" claim selection should be re-implemented in a io.quarkus.security.identity.SecurityIdentityAugmentor (inject the @io.quarkus.oidc.IdToken JsonWebToken / OidcSession), and the ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java:58` - Resolves and validates the local user for an OIDC login. this method previously implemented Spring's {@code OAuth2UserService<OidcUserRequest, OidcUser>.loadUser}. Under quarkus-oidc there is no user-request object handed to application code; instead call this logic from a {@code SecurityIdentityAugmentor} once quarkus-oidc has produced the {@code SecurityIdentity}. Provide the registration/tenant id, the merged claim map and ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java:114` - was org.springframework.security.authentication .LockedException; surface this as io.quarkus.security.AuthenticationFailedException (or a custom locked-account exception) from the SecurityIdentityAugmentor.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java:147` - was wrapped as org.springframework.security.oauth2.core.OAuth2AuthenticationException(OAuth2Error); rethrow as io.quarkus.security.AuthenticationFailedException from the augmentor.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java:163` - was OAuth2AuthenticationException("Unexpected error during authentication"); rethrow as io.quarkus.security.AuthenticationFailedException.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java:16` - this class implemented org.springframework.security.core.userdetails.UserDetailsService and returned a org.springframework.security.core.userdetails.UserDetails. Quarkus has no UserDetailsService contract; the user-loading logic below should be invoked from a Quarkus IdentityProvider (or SecurityIdentityAugmentor) that turns the returned User into a SecurityIdentity. The method is retained as a plain service returning the User ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/JwtServiceInterface.java:17` - the implementation must derive the username/claims from SecurityIdentity (getPrincipal()/getRoles()) instead of the former Spring Authentication.getName()/getAuthorities().
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java:684` - SessionPersistentRegistry still exposes Spring Security types (SessionInformation, UserDetails, OAuth2User). Once that collaborator is ported to a Quarkus session store, drop these Spring Security imports and adjust the principal type checks accordingly.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java:8` - SessionRegistryImpl is a Spring Security type (org.springframework.security.core.session.SessionRegistryImpl) with no Quarkus equivalent. Concurrent-session tracking must be rehosted (e.g. a custom bean backed by SessionPersistentRegistry / SecurityIdentity, or quarkus session management). The original producer was: @Bean public SessionRegistryImpl sessionRegistry() { return new SessionRegistryImpl(); }
- `app/proprietary/src/main/java/stirling/software/proprietary/security/supabase/SupabaseJwtDecoderFactory.java:12` - Produces the JWKS configuration for the proprietary Supabase login path. Only relevant when {@code security.supabase.user-login.enabled=true}. this class previously produced a Spring Security {@code org.springframework.security.oauth2.jwt.JwtDecoder} bean (Nimbus-based) via {@code @Configuration}/{@code @Bean}, conditionally registered with {@code @ConditionalOnProperty(security.supabase.user-login.enabled=true)}. Quarkus has no ...
- `app/proprietary/src/main/java/stirling/software/proprietary/service/AuditService.java:999` - Quarkus migration: was SecurityContextHolder.getContext().getAuthentication(). the original code distinguished API-key auth from web/JWT auth via `instanceof ApiKeyAuthenticationToken`. Under Quarkus the runtime principal is io.quarkus.security.identity.SecurityIdentity and ApiKeyAuthenticationToken has been reduced to a plain POJO (it is no longer the identity type), so the API-key vs WEB distinction can no longer be made by ...
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:74` - SecurityIdentity replaces Spring's Authentication. The collaborator FileStorageService still exposes canAccessShareLink(FileShare, org.springframework.security .core.Authentication) and recordShareAccess(FileShare, Authentication, boolean). Once that service is migrated those methods should accept SecurityIdentity (or io.quarkus.security SecurityContext) and this injected identity can be passed through directly.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:271` - canAccessShareLink/recordShareAccess still take Spring Authentication. Passing null preserves the anonymous-deny behavior until the service is migrated to SecurityIdentity; once migrated, pass `securityIdentity` through instead.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:296` - canAccessShareLink still takes Spring Authentication; pass `securityIdentity` once FileStorageService is migrated.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:380` - Spring's Authentication-based anonymous check is replaced by SecurityIdentity. Verify "anonymous" semantics match once the security layer is migrated.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/service/FolderService.java:435` - a Quarkus SecurityIdentityAugmentor/IdentityProvider must attach the stirling.software.proprietary.security.model.User entity as the SecurityIdentity principal (Spring exposed it directly via Authentication#getPrincipal, since User used to implement UserDetails). Until that augmentor exists, this only resolves when the principal IS the User entity; otherwise it rejects as 401 rather than guessing at a username->User lookup.
- `app/proprietary/src/test/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandlerTest.java:26` - Spring Boot test framework not available in Quarkus
- `app/proprietary/src/test/java/stirling/software/proprietary/security/oauth2/TauriAuthorizationRequestResolverTest.java:15` - Spring Boot test framework not available in Quarkus
- `app/proprietary/src/test/java/stirling/software/proprietary/security/service/CustomOAuth2UserServiceDebugLoggingTest.java:46` - Spring Boot test framework not available in Quarkus
- `app/saas/src/main/java/stirling/software/saas/security/EnhancedJwtAuthenticationToken.java:15` - JWT auth token that exposes the Supabase subject UUID and email alongside the standard claims, so downstream code (audit, credit accounting) can avoid re-parsing the JWT every request. TODO: Migration required - originally extended {@code org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken}. That Spring type has no Quarkus equivalent; it now extends the {@link AbstractAuthenticationToken} common shim and carries the {@link JsonWebToken} as token/principal...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseSecurityConfig.java:84` - TODO: Migration required - original @Bean JwtDecoder jwtDecoder() built a NimbusJwtDecoder from the Supabase JWKS endpoint (issuer + "/.well-known/jwks.json") and attached a SupabaseTokenValidator (iss/exp/aud enforcement with clock skew), failing closed when the issuer was unusable. NimbusJwtDecoder / JwtDecoder are Spring OAuth2 types with no Quarkus equivalent; configure Quarkus OIDC (quarkus.oidc.auth-server-url / mp.jwt.verify.* ) to point at the Supabase JWKS instead. The issuer validat...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseSecurityConfig.java:119` - Validates iss, exp (with clock-skew) and optionally aud on a decoded Supabase JWT. TODO: Migration required - originally implemented Spring's {@code OAuth2TokenValidator<Jwt>} and returned {@code OAuth2TokenValidatorResult}. Those Spring OAuth2 types are gone; the validation now operates on {@link JsonWebToken} and returns the list of error messages (empty == valid). Re-wire this into Quarkus OIDC token validation.
- `app/saas/src/main/java/stirling/software/saas/util/AuthenticationUtils.java:95` - JsonWebToken principal from the Quarkus OIDC/JWT resource server TODO: Migration required - was Spring's org.springframework.security.oauth2.jwt.Jwt; getClaimAsString("email") replaced with MicroProfile JsonWebToken.getClaim("email").
- `app/saas/src/main/java/stirling/software/saas/security/EnhancedJwtAuthenticationToken.java:15` - JWT auth token that exposes the Supabase subject UUID and email alongside the standard claims, so downstream code (audit, credit accounting) can avoid re-parsing the JWT every request. originally extended {@code org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken}. That Spring type has no Quarkus equivalent; it now extends the {@link AbstractAuthenticationToken} common shim and carries the ...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseSecurityConfig.java:84` - original @Bean JwtDecoder jwtDecoder() built a NimbusJwtDecoder from the Supabase JWKS endpoint (issuer + "/.well-known/jwks.json") and attached a SupabaseTokenValidator (iss/exp/aud enforcement with clock skew), failing closed when the issuer was unusable. NimbusJwtDecoder / JwtDecoder are Spring OAuth2 types with no Quarkus equivalent; configure Quarkus OIDC (quarkus.oidc.auth-server-url / mp.jwt.verify.* ) to point at the ...
- `app/saas/src/main/java/stirling/software/saas/security/SupabaseSecurityConfig.java:119` - Validates iss, exp (with clock-skew) and optionally aud on a decoded Supabase JWT. originally implemented Spring's {@code OAuth2TokenValidator<Jwt>} and returned {@code OAuth2TokenValidatorResult}. Those Spring OAuth2 types are gone; the validation now operates on {@link JsonWebToken} and returns the list of error messages (empty == valid). Re-wire this into Quarkus OIDC token validation.
- `app/saas/src/main/java/stirling/software/saas/util/AuthenticationUtils.java:95` - JsonWebToken principal from the Quarkus OIDC/JWT resource server was Spring's org.springframework.security.oauth2.jwt.Jwt; getClaimAsString("email") replaced with MicroProfile JsonWebToken.getClaim("email").
</details>
<details><summary><b>Conditional beans (@ConditionalOn*) -> runtime guards</b> (24)</summary>
- `app/common/src/main/java/stirling/software/common/cluster/inprocess/InProcessClusterConfiguration.java:22` - TODO: Migration required - the original @ConditionalOnExpression ("!${cluster.enabled:false} || '${cluster.backplane:inprocess}'.equalsIgnoreCase('inprocess')") gated activation of this whole configuration on a SpEL expression over two config properties. Quarkus/CDI has no direct equivalent for conditionally registering a producer set based on a SpEL boolean. The @DefaultBean producers below now always provide the in-process implementations unless another bean of the same type is present. If ...
- `app/common/src/main/java/stirling/software/common/cluster/inprocess/LocalDiskFileStoreConfiguration.java:17` - TODO: Migration required - the original class was guarded by Spring's @ConditionalOnProperty(prefix="cluster", name="artifactStore", havingValue="local", matchIfMissing=true). Quarkus has no runtime equivalent: @io.quarkus.arc.profile.IfBuildProperty is build-time only and does not support matchIfMissing semantics. The producer below is now unconditional. The "local is the default; S3 supplies its own bean" behavior is preserved via @DefaultBean (the S3 artifact-store bean, if present, wins o...
- `app/common/src/main/java/stirling/software/common/configuration/AppConfig.java:45` - <ul> <li>{@code @Bean} -> {@code @Produces}; {@code @Bean(name="x")} -> {@code @Produces @Named("x")}. <li>{@code @Value} -> {@code @ConfigProperty}; Spring {@code Environment} -> MicroProfile {@code Config}. <li>{@code @Profile("default")} flavor-default beans -> {@code @DefaultBean}: the :proprietary / :saas modules provide the "real" producer and automatically win when present, exactly like the old profile override (this is the Quarkus idiom for "default unless overridden"). <li>{@code @Sc...
- `app/core/src/main/java/stirling/software/SPDF/service/pdfjson/JobOwnershipServiceImpl.java:25` - MIGRATION: Spring's @ConditionalOnProperty(name="security.enable-login", havingValue="true") gated this bean. It is now @IfBuildProperty(security.enable-login=true) - the exact build-time complement of NoOpJobOwnershipService (@IfBuildProperty security.enable-login=false, enableIfMissing=true). The two are mutually exclusive at build time, so exactly one JobOwnershipService bean exists and callers can inject it directly (no Instance<> needed). A previous @LookupIfProperty here left both impls...
- `app/core/src/main/java/stirling/software/SPDF/service/pdfjson/NoOpJobOwnershipService.java:17` - TODO: Migration required - Spring's @ConditionalOnProperty(matchIfMissing=true) is a runtime condition; Quarkus @IfBuildProperty is evaluated at build time. enableIfMissing=true preserves the matchIfMissing default. If security.enable-login must be toggled at runtime, switch to @io.quarkus.arc.lookup.LookupIfProperty with Instance<JobOwnershipService> injection at use sites.
- `app/core/src/main/java/stirling/software/SPDF/service/telegram/TelegramPipelineBot.java:49` - TODO: Migration required - the original class was guarded by Spring's @ConditionalOnProperty(prefix="telegram", name="enabled", havingValue="true"). Migrated to a runtime guard: the bean is always created, but register() (the @PostConstruct startup hook) short-circuits when the bot token/username are not configured, so an unconfigured Telegram integration stays inert. This is a true runtime toggle (no build-time pinning required).
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/ClusterMetrics.java:22` - TODO: Migration required - original @ConditionalOnProperty(name = "cluster.enabled", havingValue = "true") was a runtime toggle. Quarkus @IfBuildProfile/@LookupIfProperty are build-time only. Either gate registration with a runtime guard on applicationProperties.getCluster().isEnabled() (e.g. skip meter registration when disabled), or use @io.quarkus.arc.lookup.LookupIfProperty if a build-time switch is acceptable.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/ClusterNodeBootstrap.java:46` - TODO: Migration required - Spring @ConditionalOnProperty(name = "cluster.enabled", havingValue = "true") was a runtime toggle. Quarkus build-time conditionals (@IfBuildProfile / @LookupIfProperty) cannot gate a StartupEvent observer at runtime, so the bean is always instantiated and the toggle is enforced at runtime via clusterEnabled below.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/s3/S3FileStoreConfiguration.java:18` - TODO: Migration required - the original Spring class was guarded by @ConditionalOnProperty(prefix="cluster", name="artifactStore", havingValue="s3") and @ConditionalOnMissingBean on the @Bean. The S3 producer below is gated with @io.quarkus.arc.lookup.LookupIfProperty(name="cluster.artifactStore", stringValue="s3"), which only contributes this FileStore when the property is "s3"; the always-on @DefaultBean producer in common's LocalDiskFileStoreConfiguration covers the "local"/default case, s...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ConditionalOnValkeyBackplane.java:23` - {@code @ConditionalOnExpression("${cluster.enabled:false} and '${cluster.backplane:inprocess}'.equals('valkey')")} SpEL guard. Quarkus/CDI has no SpEL-based conditional, but the boolean AND of two simple property checks maps directly onto two stacked (repeatable) {@link LookupIfProperty} annotations, which are evaluated with AND semantics. The Valkey producer beans are looked up only when both properties hold; otherwise the {@code @DefaultBean} in-process implementations win. TODO: Migration ...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:24` - TODO: Migration required - this class was built on spring-data-redis types (LettuceConnectionFactory, StringRedisTemplate, RedisStandaloneConfiguration, LettuceClientConfiguration, RedisPassword, RedisConnection) plus direct io.lettuce.core usage. Quarkus has no spring-data-redis; the backplane should be reworked onto io.quarkus.redis.datasource.RedisDataSource / ReactiveRedisDataSource configured via quarkus.redis.* in application.properties (hosts, password, tls, timeout=2s). The Spring imp...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyJobStore.java:41` - TODO: Migration required - @ConditionalOnValkeyBackplane (Spring @ConditionalOnExpression) is a runtime toggle on cluster.enabled + cluster.backplane=valkey. Quarkus has no direct equivalent for the composite expression; either reimplement ConditionalOnValkeyBackplane as a Quarkus build-time condition (@io.quarkus.arc.profile.IfBuildProfile / @io.quarkus.arc.lookup.LookupIfProperty) or guard bean activation at runtime. Annotation left in place pending that collaborator change. Build-time gati...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyKeyValueCache.java:18` - TODO: Migration required - @ConditionalOnValkeyBackplane (a Spring @ConditionalOnExpression composite on cluster.enabled + cluster.backplane=valkey) has no direct CDI equivalent. Once that collaborator annotation is migrated, re-guard this bean (e.g. @io.quarkus.arc.lookup.LookupIfProperty or @io.quarkus.arc.profile.IfBuildProfile, or a runtime guard) so Valkey beans only load when cluster.enabled=true AND cluster.backplane=valkey. Build-time gating: included in the build only when cluster.ba...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/McpServerController.java:36` - @ConditionalOnProperty(name = "mcp.enabled", havingValue = "true") -> LookupIfProperty. LookupIfProperty gates programmatic lookup; for a JAX-RS resource Quarkus always registers the endpoint. TODO: Migration required - to truly disable the /mcp route when mcp.enabled=false, add a runtime guard (e.g. reject in handle() when disabled) or use a build-time conditional; LookupIfProperty alone does not unregister the REST path.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/catalog/McpToolCatalog.java:34` - TODO: Migration required - the original @ConditionalOnProperty(name = "mcp.enabled", havingValue = "true") gated this bean on a runtime property. Quarkus build-time conditions (@io.quarkus.arc.lookup.LookupIfProperty / @io.quarkus.arc.profile.IfBuildProfile) cannot honour a purely runtime toggle. The bean is now always present; callers must guard on applicationProperties.getMcp() / a runtime "mcp.enabled" check, or wire @LookupIfProperty on the injection points once "mcp.enabled" is promoted ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/engine/EngineCapabilityClient.java:39` - TODO: Migration required - @ConditionalOnProperty(name = "mcp.enabled", havingValue = "true") has no direct CDI equivalent. The onReady() observer below guards on a runtime config toggle instead; consider @io.quarkus.arc.lookup.LookupIfProperty / a build-time profile if the bean itself should be excluded.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/tools/McpOperationExecutor.java:38` - TODO: Migration required - the Spring @ConditionalOnProperty(name = "mcp.enabled", havingValue = "true") guard is not directly portable. For a build-time toggle use @io.quarkus.arc.lookup.LookupIfProperty(name = "mcp.enabled", stringValue = "true") on the injection points, or gate the call sites at runtime; this bean is otherwise always created.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java:12` - TODO: Migration required - Spring @Profile("!saas") gated this scheduler so it never ran in the "saas" profile. @io.quarkus.arc.profile.UnlessBuildProfile("saas") reproduces this when "saas" is a Quarkus BUILD profile; if "saas" is only a runtime profile, this annotation has no effect and the body of resetRateLimit() must instead short-circuit on a runtime profile check (org.eclipse.microprofile.config Config "quarkus.profile" / ProfileManager.getActiveProfile()).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java:50` - MIGRATION NOTES (Spring -> Quarkus CDI): <ul> <li>{@code @Configuration} -> {@code @ApplicationScoped}; {@code @Bean} -> {@code @Produces}. <li>{@code @Qualifier("runningProOrHigher")} ctor param -> {@code @Inject} ctor with {@code @Named(...)} on the parameter (the producer lives in common {@code AppConfig}). <li>{@code @Profile("!saas")} on the producer -> {@code @UnlessBuildProfile("saas")} so the SaaS Postgres datasource shadows this H2 default exactly as the old profile override did. <li...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ee/EEAppConfig.java:31` - <ul> <li>{@code @Configuration} -> {@code @ApplicationScoped}; {@code @Bean(name="x")} -> {@code @Produces @Named("x")}. These producers deliberately omit {@code @DefaultBean} so they OVERRIDE the {@code @DefaultBean} producers declared in {@code stirling.software.common.configuration.AppConfig} whenever the :proprietary module is on the classpath - this is the Quarkus idiom for Spring's profile-based bean override. <li>{@code @Profile("security & !saas")} -> {@code @IfBuildProfile("security"...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java:31` - TODO: Migration required - Spring @ConditionalOnProperty(mail.enabled) gated bean creation. CDI has no direct runtime-toggle equivalent; this controller is always registered and instead guards at request time via the injected mail.enabled config below. If the endpoint must be fully absent when mail is disabled, wire this with @io.quarkus.arc.lookup.LookupIfProperty or a build-time @io.quarkus.arc.profile.IfBuildProfile once a build/runtime decision is made.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java:11` - TODO: Migration required - dropped @ConditionalOnProperty("mail.enabled"). This is a request DTO, not a CDI bean, so conditional bean registration does not apply. The mail.enabled gate must be enforced on the consuming endpoint/service (e.g. via @IfBuildProfile / LookupIfProperty or a runtime guard on the email controller), not on this model.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:21` - TODO: Migration required - the original class was guarded by @ConditionalOnProperty(value = "mail.enabled", havingValue = "true", matchIfMissing = false). Quarkus has no @ConditionalOnProperty. mail.enabled is a runtime property (ApplicationProperties.Mail#isEnabled) rather than a build-time flag, so the bean is always produced and callers must guard on applicationProperties.getMail().isEnabled() at call time. SMTP connection settings now live under quarkus.mailer.* config instead of MailConfig.
- `app/saas/src/main/java/stirling/software/saas/security/TeamSecurityExpressions.java:27` - TODO: Migration required - @Profile("saas") had no Quarkus equivalent here; gate bean availability via build profile / @IfBuildProfile if saas-only activation is required.
- `app/common/src/main/java/stirling/software/common/cluster/inprocess/InProcessClusterConfiguration.java:22` - the original @ConditionalOnExpression ("!${cluster.enabled:false} || '${cluster.backplane:inprocess}'.equalsIgnoreCase('inprocess')") gated activation of this whole configuration on a SpEL expression over two config properties. Quarkus/CDI has no direct equivalent for conditionally registering a producer set based on a SpEL boolean. The @DefaultBean producers below now always provide the in-process implementations unless another ...
- `app/common/src/main/java/stirling/software/common/cluster/inprocess/LocalDiskFileStoreConfiguration.java:17` - the original class was guarded by Spring's @ConditionalOnProperty(prefix="cluster", name="artifactStore", havingValue="local", matchIfMissing=true). Quarkus has no runtime equivalent: @io.quarkus.arc.profile.IfBuildProperty is build-time only and does not support matchIfMissing semantics. The producer below is now unconditional. The "local is the default; S3 supplies its own bean" behavior is preserved via @DefaultBean (the S3 ...
- `app/common/src/main/java/stirling/software/common/configuration/AppConfig.java:45` - <ul> <li>{@code @Bean} -> {@code @Produces}; {@code @Bean(name="x")} -> {@code @Produces @Named("x")}. <li>{@code @Value} -> {@code @ConfigProperty}; Spring {@code Environment} -> MicroProfile {@code Config}. <li>{@code @Profile("default")} flavor-default beans -> {@code @DefaultBean}: the :proprietary / :saas modules provide the "real" producer and automatically win when present, exactly like the old profile override (this is the Quarkus idiom for ...
- `app/core/src/main/java/stirling/software/SPDF/service/pdfjson/JobOwnershipServiceImpl.java:25` - MIGRATION: Spring's @ConditionalOnProperty(name="security.enable-login", havingValue="true") gated this bean. It is now @IfBuildProperty(security.enable-login=true) - the exact build-time complement of NoOpJobOwnershipService (@IfBuildProperty security.enable-login=false, enableIfMissing=true). The two are mutually exclusive at build time, so exactly one JobOwnershipService bean exists and callers can inject it directly (no Instance<> needed). A previous ...
- `app/core/src/main/java/stirling/software/SPDF/service/pdfjson/NoOpJobOwnershipService.java:17` - Spring's @ConditionalOnProperty(matchIfMissing=true) is a runtime condition; Quarkus @IfBuildProperty is evaluated at build time. enableIfMissing=true preserves the matchIfMissing default. If security.enable-login must be toggled at runtime, switch to @io.quarkus.arc.lookup.LookupIfProperty with Instance<JobOwnershipService> injection at use sites.
- `app/core/src/main/java/stirling/software/SPDF/service/telegram/TelegramPipelineBot.java:49` - the original class was guarded by Spring's @ConditionalOnProperty(prefix="telegram", name="enabled", havingValue="true"). Migrated to a runtime guard: the bean is always created, but register() (the @PostConstruct startup hook) short-circuits when the bot token/username are not configured, so an unconfigured Telegram integration stays inert. This is a true runtime toggle (no build-time pinning required).
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/ClusterMetrics.java:22` - original @ConditionalOnProperty(name = "cluster.enabled", havingValue = "true") was a runtime toggle. Quarkus @IfBuildProfile/@LookupIfProperty are build-time only. Either gate registration with a runtime guard on applicationProperties.getCluster().isEnabled() (e.g. skip meter registration when disabled), or use @io.quarkus.arc.lookup.LookupIfProperty if a build-time switch is acceptable.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/ClusterNodeBootstrap.java:46` - Spring @ConditionalOnProperty(name = "cluster.enabled", havingValue = "true") was a runtime toggle. Quarkus build-time conditionals (@IfBuildProfile / @LookupIfProperty) cannot gate a StartupEvent observer at runtime, so the bean is always instantiated and the toggle is enforced at runtime via clusterEnabled below.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/s3/S3FileStoreConfiguration.java:18` - the original Spring class was guarded by @ConditionalOnProperty(prefix="cluster", name="artifactStore", havingValue="s3") and @ConditionalOnMissingBean on the @Bean. The S3 producer below is gated with @io.quarkus.arc.lookup.LookupIfProperty(name="cluster.artifactStore", stringValue="s3"), which only contributes this FileStore when the property is "s3"; the always-on @DefaultBean producer in common's ...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ConditionalOnValkeyBackplane.java:23` - {@code @ConditionalOnExpression("${cluster.enabled:false} and '${cluster.backplane:inprocess}'.equals('valkey')")} SpEL guard. Quarkus/CDI has no SpEL-based conditional, but the boolean AND of two simple property checks maps directly onto two stacked (repeatable) {@link LookupIfProperty} annotations, which are evaluated with AND semantics. The Valkey producer beans are looked up only when both properties hold; otherwise the {@code @DefaultBean} in-process ...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:24` - this class was built on spring-data-redis types (LettuceConnectionFactory, StringRedisTemplate, RedisStandaloneConfiguration, LettuceClientConfiguration, RedisPassword, RedisConnection) plus direct io.lettuce.core usage. Quarkus has no spring-data-redis; the backplane should be reworked onto io.quarkus.redis.datasource.RedisDataSource / ReactiveRedisDataSource configured via quarkus.redis.* in application.properties (hosts ...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyJobStore.java:41` - @ConditionalOnValkeyBackplane (Spring @ConditionalOnExpression) is a runtime toggle on cluster.enabled + cluster.backplane=valkey. Quarkus has no direct equivalent for the composite expression; either reimplement ConditionalOnValkeyBackplane as a Quarkus build-time condition (@io.quarkus.arc.profile.IfBuildProfile / @io.quarkus.arc.lookup.LookupIfProperty) or guard bean activation at runtime. Annotation left in place pending ...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyKeyValueCache.java:18` - @ConditionalOnValkeyBackplane (a Spring @ConditionalOnExpression composite on cluster.enabled + cluster.backplane=valkey) has no direct CDI equivalent. Once that collaborator annotation is migrated, re-guard this bean (e.g. @io.quarkus.arc.lookup.LookupIfProperty or @io.quarkus.arc.profile.IfBuildProfile, or a runtime guard) so Valkey beans only load when cluster.enabled=true AND cluster.backplane=valkey. Build-time gating ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/McpServerController.java:36` - @ConditionalOnProperty(name = "mcp.enabled", havingValue = "true") -> LookupIfProperty. LookupIfProperty gates programmatic lookup; for a JAX-RS resource Quarkus always registers the endpoint. to truly disable the /mcp route when mcp.enabled=false, add a runtime guard (e.g. reject in handle() when disabled) or use a build-time conditional; LookupIfProperty alone does not unregister the REST path.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/catalog/McpToolCatalog.java:34` - the original @ConditionalOnProperty(name = "mcp.enabled", havingValue = "true") gated this bean on a runtime property. Quarkus build-time conditions (@io.quarkus.arc.lookup.LookupIfProperty / @io.quarkus.arc.profile.IfBuildProfile) cannot honour a purely runtime toggle. The bean is now always present; callers must guard on applicationProperties.getMcp() / a runtime "mcp.enabled" check, or wire @LookupIfProperty on the injection ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/engine/EngineCapabilityClient.java:39` - @ConditionalOnProperty(name = "mcp.enabled", havingValue = "true") has no direct CDI equivalent. The onReady() observer below guards on a runtime config toggle instead; consider @io.quarkus.arc.lookup.LookupIfProperty / a build-time profile if the bean itself should be excluded.
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/tools/McpOperationExecutor.java:38` - the Spring @ConditionalOnProperty(name = "mcp.enabled", havingValue = "true") guard is not directly portable. For a build-time toggle use @io.quarkus.arc.lookup.LookupIfProperty(name = "mcp.enabled", stringValue = "true") on the injection points, or gate the call sites at runtime; this bean is otherwise always created.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java:12` - Spring @Profile("!saas") gated this scheduler so it never ran in the "saas" profile. @io.quarkus.arc.profile.UnlessBuildProfile("saas") reproduces this when "saas" is a Quarkus BUILD profile; if "saas" is only a runtime profile, this annotation has no effect and the body of resetRateLimit() must instead short-circuit on a runtime profile check (org.eclipse.microprofile.config Config "quarkus.profile" / ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java:50` - MIGRATION NOTES (Spring -> Quarkus CDI): <ul> <li>{@code @Configuration} -> {@code @ApplicationScoped}; {@code @Bean} -> {@code @Produces}. <li>{@code @Qualifier("runningProOrHigher")} ctor param -> {@code @Inject} ctor with {@code @Named(...)} on the parameter (the producer lives in common {@code AppConfig}). <li>{@code @Profile("!saas")} on the producer -> {@code @UnlessBuildProfile("saas")} so the SaaS Postgres datasource shadows this H2 default ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ee/EEAppConfig.java:31` - <ul> <li>{@code @Configuration} -> {@code @ApplicationScoped}; {@code @Bean(name="x")} -> {@code @Produces @Named("x")}. These producers deliberately omit {@code @DefaultBean} so they OVERRIDE the {@code @DefaultBean} producers declared in {@code stirling.software.common.configuration.AppConfig} whenever the :proprietary module is on the classpath - this is the Quarkus idiom for Spring's profile-based bean override. <li>{@code @Profile("security & ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java:31` - Spring @ConditionalOnProperty(mail.enabled) gated bean creation. CDI has no direct runtime-toggle equivalent; this controller is always registered and instead guards at request time via the injected mail.enabled config below. If the endpoint must be fully absent when mail is disabled, wire this with @io.quarkus.arc.lookup.LookupIfProperty or a build-time @io.quarkus.arc.profile.IfBuildProfile once a build/runtime decision is ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java:11` - dropped @ConditionalOnProperty("mail.enabled"). This is a request DTO, not a CDI bean, so conditional bean registration does not apply. The mail.enabled gate must be enforced on the consuming endpoint/service (e.g. via @IfBuildProfile / LookupIfProperty or a runtime guard on the email controller), not on this model.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:21` - the original class was guarded by @ConditionalOnProperty(value = "mail.enabled", havingValue = "true", matchIfMissing = false). Quarkus has no @ConditionalOnProperty. mail.enabled is a runtime property (ApplicationProperties.Mail#isEnabled) rather than a build-time flag, so the bean is always produced and callers must guard on applicationProperties.getMail().isEnabled() at call time. SMTP connection settings now live under ...
- `app/saas/src/main/java/stirling/software/saas/security/TeamSecurityExpressions.java:27` - @Profile("saas") had no Quarkus equivalent here; gate bean availability via build profile / @IfBuildProfile if saas-only activation is required.
</details>
<details><summary><b>Spring Data -> Panache</b> (5)</summary>
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:65` - jakarta.ws.rs.ext.ExceptionMapper}. Because JAX-RS resolves at most one mapper per exception type, this single {@code ExceptionMapper<Throwable>} reproduces the original per-type {@code @ExceptionHandler} dispatch by inspecting the thrown exception with {@code instanceof}. The RFC 7807 body, previously a Spring {@code ProblemDetail}, is now built as an ordered {@link java.util.Map} (serialized by quarkus-rest-jackson) to preserve the exact response shape without depending on Spring types. <h2...
- `app/proprietary/src/main/java/stirling/software/proprietary/repository/PersistentAuditEventRepository.java:24` - are preserved verbatim and executed through Panache's {@link #find(String, Object...)} / {@link #find(String, io.quarkus.panache.common.Sort, java.util.Map)} APIs. TODO: Migration required - the previous Spring Data signatures returned {@code org.springframework.data.domain.Page<T>} and accepted {@code org.springframework.data.domain.Pageable}. Those Spring types are gone in Quarkus; the paged finders below now return a Panache {@link PanacheQuery} and accept an {@code io.quarkus.panache.comm...
- `app/proprietary/src/main/java/stirling/software/proprietary/repository/PersistentAuditEventRepository.java:197` - Find IDs for batch deletion - using JPQL with paging instead of a native query. TODO: Migration required - originally accepted a Spring {@code Pageable}; callers must pass an {@code io.quarkus.panache.common.Page} instead (see class doc).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/TeamController.java:247` - TODO: Migration required - teamRepository/userRepository still extend Spring Data JpaRepository. Once they are migrated to Panache, findById(...) returns the entity directly (not Optional); update the Optional handling above accordingly. Likewise save(...) -> persist(...), delete(...) -> delete(...)/deleteById(...). Derived finders existsByNameIgnoreCase / countByTeam must be reimplemented as Panache default methods.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/service/FolderService.java:268` - TODO: Migration required - StoredFileRepository is still a Spring Data JpaRepository; save()/saveAll()/flush() resolve against it for now. When that repository is ported to a Panache repository, map these to persist()/flush() accordingly.
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:65` - jakarta.ws.rs.ext.ExceptionMapper}. Because JAX-RS resolves at most one mapper per exception type, this single {@code ExceptionMapper<Throwable>} reproduces the original per-type {@code @ExceptionHandler} dispatch by inspecting the thrown exception with {@code instanceof}. The RFC 7807 body, previously a Spring {@code ProblemDetail}, is now built as an ordered {@link java.util.Map} (serialized by quarkus-rest-jackson) to preserve the exact response shape ...
- `app/proprietary/src/main/java/stirling/software/proprietary/repository/PersistentAuditEventRepository.java:24` - are preserved verbatim and executed through Panache's {@link #find(String, Object...)} / {@link #find(String, io.quarkus.panache.common.Sort, java.util.Map)} APIs. the previous Spring Data signatures returned {@code org.springframework.data.domain.Page<T>} and accepted {@code org.springframework.data.domain.Pageable}. Those Spring types are gone in Quarkus; the paged finders below now return a Panache {@link PanacheQuery} and ...
- `app/proprietary/src/main/java/stirling/software/proprietary/repository/PersistentAuditEventRepository.java:197` - Find IDs for batch deletion - using JPQL with paging instead of a native query. originally accepted a Spring {@code Pageable}; callers must pass an {@code io.quarkus.panache.common.Page} instead (see class doc).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/TeamController.java:247` - teamRepository/userRepository still extend Spring Data JpaRepository. Once they are migrated to Panache, findById(...) returns the entity directly (not Optional); update the Optional handling above accordingly. Likewise save(...) -> persist(...), delete(...) -> delete(...)/deleteById(...). Derived finders existsByNameIgnoreCase / countByTeam must be reimplemented as Panache default methods.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/service/FolderService.java:268` - StoredFileRepository is still a Spring Data JpaRepository; save()/saveAll()/flush() resolve against it for now. When that repository is ported to a Panache repository, map these to persist()/flush() accordingly.
</details>
<details><summary><b>MVC view / template rendering -> Qute or static</b> (14)</summary>
- `app/common/src/main/java/stirling/software/common/util/ErrorUtils.java:10` - TODO: Migration required - server-rendered error view removed; surface via JAX-RS ExceptionMapper. Spring MVC org.springframework.ui.Model has no Quarkus/Jakarta (JAX-RS) drop-in; the method now mutates and returns a plain Map<String, Object> model holder.
- `app/common/src/main/java/stirling/software/common/util/ErrorUtils.java:23` - TODO: Migration required - server-rendered error view removed; surface via JAX-RS ExceptionMapper. Spring MVC org.springframework.web.servlet.ModelAndView has no Quarkus/Jakarta (JAX-RS) drop-in; the method now returns a plain Map<String, Object> model holder instead of a ModelAndView (the incoming model parameter is retained for signature compatibility but is no longer the Spring Model type).
- `app/core/src/main/resources/application.properties:62` - ---- Error handling (was spring.web.error.* / spring.mvc.problemdetails.enabled=false) -------- TODO: Migration required - GlobalExceptionHandler is an @ControllerAdvice; rewrite as JAX-RS ExceptionMapper(s) producing RFC 7807 ProblemDetail responses. The Spring error-page / whitelabel settings below have no Quarkus property equivalent: spring.web.error.path=/error, whitelabel.enabled=false, include-stacktrace/exception/message=always
- `app/proprietary/build.gradle:16` - ---- Spring -> Quarkus extension mapping (full native migration) ---- spring-jdbc -> Agroal datasource (transitive via hibernate-orm). JdbcTemplate usage, if any, must be rewritten to plain JDBC / Panache. TODO: Migration required - replace any org.springframework.jdbc.core.JdbcTemplate usage. spring-webmvc -> quarkus-rest (inherited api-scoped from :common).
- `app/proprietary/build.gradle:30` - spring-boot-starter-data-redis -> quarkus-redis-client (used by the optional Valkey backplane). TODO: Migration required - rewrite RedisTemplate/Lettuce usage on the Quarkus Redis client API.
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditDashboardWebController.java:35` - Spring's org.springframework.ui.Model + view-name ("audit/dashboard") drove Thymeleaf server-side rendering. Quarkus has no Thymeleaf view resolver; the equivalent is a Qute TemplateInstance bound to src/main/resources/templates/audit/dashboard.html. TODO: Migration required - rebind this view to Qute. Inject @io.quarkus.qute.Location("audit/dashboard") io.quarkus.qute.Template dashboard; and return dashboard.data(...) as a TemplateInstance (with a Qute RestEasy extension), or render the page...
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditDashboardWebController.java:53` - TODO: Migration required - return the rendered Qute template instead of this placeholder once audit/dashboard.html is migrated. The attributes in `model` map 1:1 to the former Spring Model attributes.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyClusterBackplane.java:25` - TODO: Migration required - was Spring spring-data-redis StringRedisTemplate. Replaced with Quarkus RedisDataSource (io.quarkus.redis.datasource). Verify the redis client extension (quarkus-redis-client) is on the classpath and configured via quarkus.redis.* properties.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyClusterBackplane.java:37` - Original used template.execute() so the connection was borrowed from the pool and returned in a finally block - critical because isHealthy() is hit on every k8s liveness/readiness probe tick. Quarkus RedisDataSource manages connection pooling/return internally, so issuing a single command (PING) is the equivalent. TODO: Migration required - confirm command mapping. Quarkus exposes PING via the low-level command API: redisDataSource.execute("PING") returns a Response whose toString() is the si...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:86` - MIGRATION: the former @Produces RedisDataSource methods (valkeyConnectionFactory / valkeyTemplate) were removed - they only handed back the container-managed RedisDataSource and produced two @Default beans of the same type, which Arc flagged as an ambiguous dependency for every consumer that injects a plain RedisDataSource. All Valkey* collaborators now inject the Quarkus-provided RedisDataSource directly. TODO: Migration required - the eager boot handshake / URL+TLS validation that used to r...
- `app/saas/src/main/java/stirling/software/saas/ai/controller/AiProxyController.java:155` - TODO: Migration required - Spring's "/output/**" wildcard mapping has no direct JAX-RS equivalent; using a {path:.*} regex template to capture the trailing path segments.
- `app/saas/src/main/java/stirling/software/saas/config/SaasRestTemplateConfig.java:15` - HTTP client for talking to Supabase Edge Functions, with a bounded connect timeout. TODO: Migration required - replaced Spring RestTemplate with java.net.http.HttpClient. Consider a typed {@code @RegisterRestClient} client instead. Note: the per-request read timeout previously set on RestTemplate must now be applied per HttpRequest via {@code HttpRequest.Builder#timeout}.
- `app/saas/src/main/java/stirling/software/saas/service/SaasTeamService.java:43` - TODO: Migration required - Spring RestTemplate replaced with JDK java.net.http.HttpClient for the Supabase edge-function email POST (see sendInvitationEmail).
- `app/saas/src/main/java/stirling/software/saas/service/SaasTeamService.java:705` - TODO: Migration required - Spring RestTemplate (HttpHeaders/MediaType/HttpEntity + postForEntity) replaced with JDK HttpClient. Preserves the JSON POST with the bearer Authorization header to the Supabase edge function.
- `app/common/src/main/java/stirling/software/common/util/ErrorUtils.java:10` - server-rendered error view removed; surface via JAX-RS ExceptionMapper. Spring MVC org.springframework.ui.Model has no Quarkus/Jakarta (JAX-RS) drop-in; the method now mutates and returns a plain Map<String, Object> model holder.
- `app/common/src/main/java/stirling/software/common/util/ErrorUtils.java:23` - server-rendered error view removed; surface via JAX-RS ExceptionMapper. Spring MVC org.springframework.web.servlet.ModelAndView has no Quarkus/Jakarta (JAX-RS) drop-in; the method now returns a plain Map<String, Object> model holder instead of a ModelAndView (the incoming model parameter is retained for signature compatibility but is no longer the Spring Model type).
- `app/core/src/main/resources/application.properties:62` - ---- Error handling (was spring.web.error.* / spring.mvc.problemdetails.enabled=false) -------- GlobalExceptionHandler is an @ControllerAdvice; rewrite as JAX-RS ExceptionMapper(s) producing RFC 7807 ProblemDetail responses. The Spring error-page / whitelabel settings below have no Quarkus property equivalent: spring.web.error.path=/error, whitelabel.enabled=false, include-stacktrace/exception/message=always
- `app/proprietary/build.gradle:16` - ---- Spring -> Quarkus extension mapping (full native migration) ---- spring-jdbc -> Agroal datasource (transitive via hibernate-orm). JdbcTemplate usage, if any, must be rewritten to plain JDBC / Panache. replace any org.springframework.jdbc.core.JdbcTemplate usage. spring-webmvc -> quarkus-rest (inherited api-scoped from :common).
- `app/proprietary/build.gradle:30` - spring-boot-starter-data-redis -> quarkus-redis-client (used by the optional Valkey backplane). rewrite RedisTemplate/Lettuce usage on the Quarkus Redis client API.
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditDashboardWebController.java:35` - Spring's org.springframework.ui.Model + view-name ("audit/dashboard") drove Thymeleaf server-side rendering. Quarkus has no Thymeleaf view resolver; the equivalent is a Qute TemplateInstance bound to src/main/resources/templates/audit/dashboard.html. rebind this view to Qute. Inject @io.quarkus.qute.Location("audit/dashboard") io.quarkus.qute.Template dashboard; and return dashboard.data(...) as a TemplateInstance (with a Qute ...
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditDashboardWebController.java:53` - return the rendered Qute template instead of this placeholder once audit/dashboard.html is migrated. The attributes in `model` map 1:1 to the former Spring Model attributes.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyClusterBackplane.java:25` - was Spring spring-data-redis StringRedisTemplate. Replaced with Quarkus RedisDataSource (io.quarkus.redis.datasource). Verify the redis client extension (quarkus-redis-client) is on the classpath and configured via quarkus.redis.* properties.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyClusterBackplane.java:37` - Original used template.execute() so the connection was borrowed from the pool and returned in a finally block - critical because isHealthy() is hit on every k8s liveness/readiness probe tick. Quarkus RedisDataSource manages connection pooling/return internally, so issuing a single command (PING) is the equivalent. confirm command mapping. Quarkus exposes PING via the low-level command API: redisDataSource.execute("PING") returns ...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:86` - MIGRATION: the former @Produces RedisDataSource methods (valkeyConnectionFactory / valkeyTemplate) were removed - they only handed back the container-managed RedisDataSource and produced two @Default beans of the same type, which Arc flagged as an ambiguous dependency for every consumer that injects a plain RedisDataSource. All Valkey* collaborators now inject the Quarkus-provided RedisDataSource directly. the eager boot ...
- `app/saas/src/main/java/stirling/software/saas/ai/controller/AiProxyController.java:155` - Spring's "/output/**" wildcard mapping has no direct JAX-RS equivalent; using a {path:.*} regex template to capture the trailing path segments.
- `app/saas/src/main/java/stirling/software/saas/config/SaasRestTemplateConfig.java:15` - HTTP client for talking to Supabase Edge Functions, with a bounded connect timeout. replaced Spring RestTemplate with java.net.http.HttpClient. Consider a typed {@code @RegisterRestClient} client instead. Note: the per-request read timeout previously set on RestTemplate must now be applied per HttpRequest via {@code HttpRequest.Builder#timeout}.
- `app/saas/src/main/java/stirling/software/saas/service/SaasTeamService.java:43` - Spring RestTemplate replaced with JDK java.net.http.HttpClient for the Supabase edge-function email POST (see sendInvitationEmail).
- `app/saas/src/main/java/stirling/software/saas/service/SaasTeamService.java:705` - Spring RestTemplate (HttpHeaders/MediaType/HttpEntity + postForEntity) replaced with JDK HttpClient. Preserves the JSON POST with the bearer Authorization header to the Supabase edge function.
</details>
<details><summary><b>Spring config/env -> MicroProfile Config</b> (10)</summary>
- `app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java:45` - TODO: Migration required - rebind via @io.smallrye.config.ConfigMapping or @io.quarkus.arc.config.ConfigProperties. Was Spring @ConfigurationProperties(prefix = ""), kept here as a plain CDI bean POJO; the property binding is not yet wired in Quarkus. TODO: Migration required - Spring @Order(Ordered.HIGHEST_PRECEDENCE) controlled configuration-bean ordering; there is no equivalent CDI ordering annotation for this bean.
- `app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java:84` - REMOVED (Spring -> Quarkus): dynamicYamlPropertySource(ConfigurableEnvironment). This was a Spring @Bean that registered settings.yml as an extra runtime PropertySource on the ConfigurableEnvironment (added first, or last under the "saas" profile). Quarkus has no ConfigurableEnvironment/PropertySource model and the @Bean had already been removed, so the method was dead code referencing Spring-only types. TODO: Migration required - reimplement external settings.yml loading as a custom org.ecli...
- `app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java:45` - rebind via @io.smallrye.config.ConfigMapping or @io.quarkus.arc.config.ConfigProperties. Was Spring @ConfigurationProperties(prefix = ""), kept here as a plain CDI bean POJO; the property binding is not yet wired in Quarkus. Spring @Order(Ordered.HIGHEST_PRECEDENCE) controlled configuration-bean ordering; there is no equivalent CDI ordering annotation for this bean.
- `app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java:84` - REMOVED (Spring -> Quarkus): dynamicYamlPropertySource(ConfigurableEnvironment). This was a Spring @Bean that registered settings.yml as an extra runtime PropertySource on the ConfigurableEnvironment (added first, or last under the "saas" profile). Quarkus has no ConfigurableEnvironment/PropertySource model and the @Bean had already been removed, so the method was dead code referencing Spring-only types. reimplement external ...
- `app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesDynamicYamlPropertySourceTest.java:18` - Spring Boot test framework not available in Quarkus
- `app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java:70` - TODO: Migration required - the Spring "spring.config.additional-location" property used to load the external settings/customSettings YAML files into the environment. Quarkus uses SmallRye Config; wire these files via a config source instead, e.g. set the system property "smallrye.config.locations" to the (comma-separated) file: URLs before this point, or register a custom ConfigSourceFactory. The directories/log lines above are preserved.
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:114` - TODO: Migration required - development mode used to be derived from Spring active profiles via org.springframework.core.env.Environment. Quarkus exposes the profile through io.quarkus.runtime.LaunchMode / quarkus.profile; this is read here from the standard config so no Spring Environment is needed.
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:902` - TODO: Migration required - this replaces Spring's Environment.getActiveProfiles() ("dev"/"development") check. Quarkus exposes the active profile via io.quarkus.runtime.LaunchMode and the "quarkus.profile" config key; read it from the standard config so no Spring Environment bean is required.
- `app/proprietary/src/main/java/stirling/software/proprietary/config/AuditConfigurationProperties.java:16` - TODO: Migration required - Spring @Order(HIGHEST_PRECEDENCE + 10) had no direct CDI equivalent; bean ordering/precedence must be handled via @Priority or explicit ordering at injection points if it was relied upon.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java:44` - TODO: Migration required - @Conditional(H2SQLCondition.class) gated this controller on the datasource being H2 (driver/url inspection of the Spring Environment). Quarkus has no @Conditional equivalent; this must be re-expressed either as a build-time @IfBuildProfile, a runtime @LookupIfProperty on a datasource property, or a runtime guard inside DatabaseService that no-ops/returns 404 when the active datasource is not H2.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/supabase/SupabaseUserLoginProperties.java:8` - TODO: Migration required - this was a Spring @ConfigurationProperties(prefix = "security.supabase.user-login") POJO. Rebind the prefixed properties via @io.smallrye.config.ConfigMapping(prefix = "security.supabase.user-login") (interface-based) so the fields are populated from configuration; until then this bean holds defaults only.
- `app/saas/src/main/java/stirling/software/saas/config/SupabaseConfigurationProperties.java:11` - TODO: Migration required - @ConfigurationProperties(prefix="app.supabase"); bind via @ConfigProperty or @ConfigMapping
- `app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java:70` - the Spring "spring.config.additional-location" property used to load the external settings/customSettings YAML files into the environment. Quarkus uses SmallRye Config; wire these files via a config source instead, e.g. set the system property "smallrye.config.locations" to the (comma-separated) file: URLs before this point, or register a custom ConfigSourceFactory. The directories/log lines above are preserved.
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:114` - development mode used to be derived from Spring active profiles via org.springframework.core.env.Environment. Quarkus exposes the profile through io.quarkus.runtime.LaunchMode / quarkus.profile; this is read here from the standard config so no Spring Environment is needed.
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:902` - this replaces Spring's Environment.getActiveProfiles() ("dev"/"development") check. Quarkus exposes the active profile via io.quarkus.runtime.LaunchMode and the "quarkus.profile" config key; read it from the standard config so no Spring Environment bean is required.
- `app/proprietary/src/main/java/stirling/software/proprietary/config/AuditConfigurationProperties.java:16` - Spring @Order(HIGHEST_PRECEDENCE + 10) had no direct CDI equivalent; bean ordering/precedence must be handled via @Priority or explicit ordering at injection points if it was relied upon.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java:44` - @Conditional(H2SQLCondition.class) gated this controller on the datasource being H2 (driver/url inspection of the Spring Environment). Quarkus has no @Conditional equivalent; this must be re-expressed either as a build-time @IfBuildProfile, a runtime @LookupIfProperty on a datasource property, or a runtime guard inside DatabaseService that no-ops/returns 404 when the active datasource is not H2.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/supabase/SupabaseUserLoginProperties.java:8` - this was a Spring @ConfigurationProperties(prefix = "security.supabase.user-login") POJO. Rebind the prefixed properties via @io.smallrye.config.ConfigMapping(prefix = "security.supabase.user-login") (interface-based) so the fields are populated from configuration; until then this bean holds defaults only.
- `app/saas/src/main/java/stirling/software/saas/config/SupabaseConfigurationProperties.java:11` - @ConfigurationProperties(prefix="app.supabase"); bind via @ConfigProperty or @ConfigMapping
</details>
@@ -445,134 +445,134 @@ corresponding feature. Grouped by concern.
<details><summary><b>Scheduling / async</b> (14)</summary>
- `app/common/src/main/java/stirling/software/common/configuration/SchedulingConfig.java:15` - Quarkus' {@code quarkus-scheduler} extension owns the scheduling thread pool, so no application bean is required. To keep the "each scheduled task on its own virtual thread" behaviour, annotate the individual {@code @io.quarkus.scheduler.Scheduled} methods with {@code @io.smallrye.common.annotation.RunOnVirtualThread} (or configure {@code quarkus.scheduler.use-virtual-threads=true} where supported). TODO: Migration required - any injection point that received the former Spring {@code TaskSche...
- `app/common/src/main/java/stirling/software/common/service/TempFileCleanupService.java:132` - Scheduled task to clean up old temporary files. Runs at the configured interval. TODO: Migration required - the Spring form used a SpEL expression ({@code fixedDelayString="#{applicationProperties.system.tempFileManagement.cleanupIntervalMinutes}"}). Quarkus {@code @Scheduled} cannot reference an arbitrary bean property; {@code every} only resolves a MicroProfile Config placeholder. The cleanup interval must therefore be exposed as a config key (e.g. {@code stirling.temp.cleanup-interval}) bo...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/ClusterNodeBootstrap.java:94` - TODO: Migration required - Spring @Scheduled(fixedDelayString = "${cluster.node.heartbeat-interval-ms:5000}") drove the interval directly from config in milliseconds. Quarkus @Scheduled "every" expects a Duration string, so the config reference "{cluster.node.heartbeat-interval-ms}" cannot be reused as-is (it resolves to a bare number). Hard-coded to 5s to match the model default; if the interval is operator-tunable, expose a duration-formatted property (e.g. cluster.node.heartbeat-interval=5...
- `app/proprietary/src/main/java/stirling/software/proprietary/config/CustomAuditEventRepository.java:46` - TODO: Migration required - was @Async("auditExecutor") (Spring async executor). Quarkus has no @Async; run this off the request thread via a managed executor (e.g. inject org.eclipse.microprofile.context.ManagedExecutor and submit, or annotate with @io.smallrye.common.annotation.Blocking on a reactive path). Logic is kept synchronous for now to avoid changing behavior incorrectly.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ee/LicenseKeyChecker.java:58` - TODO: Migration required - Spring used initialDelay=fixedRate=7d. Quarkus @Scheduled has no initialDelay equivalent for fixed-rate; "every=P7D" fires the first run 7 days after start, which preserves the original initial-delay semantics. delayed="..." could add an extra offset if needed. MIGRATION: every="7d" was rejected ("Invalid every() expression") because Quarkus parses the value as a Duration and a bare "7d" maps to the invalid "PT7d". Use the ISO-8601 period form P7D (7 days), which Du...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java:23` - TODO: Migration required - the original bean used @Conditional(H2SQLCondition.class) to skip registration entirely when not running on H2. Quarkus has no runtime @Conditional, so the gate is evaluated at runtime here via h2SQLCondition.matches() and the backup is short-circuited when false. The schedule still fires on the configured cron but becomes a no-op off H2. TODO: Migration required - the Spring cron was a SpEL expression "#{applicationProperties.system.databaseBackup.cron}". Quarkus @...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:46` - TODO: Migration required - Spring's @Async ran this on a managed executor. Quarkus has no @Async; the method now runs synchronously on the caller's thread. To restore async behaviour wrap the body in io.smallrye.mutiny.Uni or submit to a jakarta.enterprise.concurrent ManagedExecutor (would change the void signature, so deferred).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:100` - TODO: Migration required - @Async dropped (no Quarkus equivalent); now runs synchronously.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:125` - TODO: Migration required - @Async dropped (no Quarkus equivalent); now runs synchronously.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:151` - TODO: Migration required - @Async dropped (no Quarkus equivalent); now runs synchronously.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:211` - TODO: Migration required - @Async dropped (no Quarkus equivalent); now runs synchronously.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:257` - TODO: Migration required - @Async dropped (no Quarkus equivalent); now runs synchronously.
- `app/proprietary/src/main/java/stirling/software/proprietary/service/AiUserDataService.java:33` - TODO: Migration required - Spring's @Async ran this fire-and-forget on a managed executor so an unavailable engine never delayed the logout response. Quarkus has no @Async; the method now runs synchronously on the caller's thread. To restore off-thread dispatch, inject a jakarta.enterprise.concurrent.ManagedExecutorService (or annotate the calling REST endpoint with @io.smallrye.common.annotation.RunOnVirtualThread). Errors are still swallowed, so the only behavioural change is that the calle...
- `app/saas/src/main/java/stirling/software/saas/payg/job/StaleJobCloser.java:49` - TODO: Migration required - was configurable via property payg.job.stale-close-interval-ms (default 60000ms). io.quarkus.scheduler.Scheduled#every is a fixed string; restore configurability with @Scheduled(every = "{payg.job.stale-close-interval}") + a Duration config property if the interval must stay tunable.
- `app/common/src/main/java/stirling/software/common/configuration/SchedulingConfig.java:15` - Quarkus' {@code quarkus-scheduler} extension owns the scheduling thread pool, so no application bean is required. To keep the "each scheduled task on its own virtual thread" behaviour, annotate the individual {@code @io.quarkus.scheduler.Scheduled} methods with {@code @io.smallrye.common.annotation.RunOnVirtualThread} (or configure {@code quarkus.scheduler.use-virtual-threads=true} where supported). any injection point that ...
- `app/common/src/main/java/stirling/software/common/service/TempFileCleanupService.java:132` - Scheduled task to clean up old temporary files. Runs at the configured interval. the Spring form used a SpEL expression ({@code fixedDelayString="#{applicationProperties.system.tempFileManagement.cleanupIntervalMinutes}"}). Quarkus {@code @Scheduled} cannot reference an arbitrary bean property; {@code every} only resolves a MicroProfile Config placeholder. The cleanup interval must therefore be exposed as a config key (e.g ...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/ClusterNodeBootstrap.java:94` - Spring @Scheduled(fixedDelayString = "${cluster.node.heartbeat-interval-ms:5000}") drove the interval directly from config in milliseconds. Quarkus @Scheduled "every" expects a Duration string, so the config reference "{cluster.node.heartbeat-interval-ms}" cannot be reused as-is (it resolves to a bare number). Hard-coded to 5s to match the model default; if the interval is operator-tunable, expose a duration-formatted property ...
- `app/proprietary/src/main/java/stirling/software/proprietary/config/CustomAuditEventRepository.java:46` - was @Async("auditExecutor") (Spring async executor). Quarkus has no @Async; run this off the request thread via a managed executor (e.g. inject org.eclipse.microprofile.context.ManagedExecutor and submit, or annotate with @io.smallrye.common.annotation.Blocking on a reactive path). Logic is kept synchronous for now to avoid changing behavior incorrectly.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ee/LicenseKeyChecker.java:58` - Spring used initialDelay=fixedRate=7d. Quarkus @Scheduled has no initialDelay equivalent for fixed-rate; "every=P7D" fires the first run 7 days after start, which preserves the original initial-delay semantics. delayed="..." could add an extra offset if needed. MIGRATION: every="7d" was rejected ("Invalid every() expression") because Quarkus parses the value as a Duration and a bare "7d" maps to the invalid "PT7d". Use the ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java:23` - the original bean used @Conditional(H2SQLCondition.class) to skip registration entirely when not running on H2. Quarkus has no runtime @Conditional, so the gate is evaluated at runtime here via h2SQLCondition.matches() and the backup is short-circuited when false. The schedule still fires on the configured cron but becomes a no-op off H2. the Spring cron was a SpEL expression ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:46` - Spring's @Async ran this on a managed executor. Quarkus has no @Async; the method now runs synchronously on the caller's thread. To restore async behaviour wrap the body in io.smallrye.mutiny.Uni or submit to a jakarta.enterprise.concurrent ManagedExecutor (would change the void signature, so deferred).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:100` - @Async dropped (no Quarkus equivalent); now runs synchronously.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:125` - @Async dropped (no Quarkus equivalent); now runs synchronously.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:151` - @Async dropped (no Quarkus equivalent); now runs synchronously.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:211` - @Async dropped (no Quarkus equivalent); now runs synchronously.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java:257` - @Async dropped (no Quarkus equivalent); now runs synchronously.
- `app/proprietary/src/main/java/stirling/software/proprietary/service/AiUserDataService.java:33` - Spring's @Async ran this fire-and-forget on a managed executor so an unavailable engine never delayed the logout response. Quarkus has no @Async; the method now runs synchronously on the caller's thread. To restore off-thread dispatch, inject a jakarta.enterprise.concurrent.ManagedExecutorService (or annotate the calling REST endpoint with @io.smallrye.common.annotation.RunOnVirtualThread). Errors are still swallowed, so the ...
- `app/saas/src/main/java/stirling/software/saas/payg/job/StaleJobCloser.java:49` - was configurable via property payg.job.stale-close-interval-ms (default 60000ms). io.quarkus.scheduler.Scheduled#every is a fixed string; restore configurability with @Scheduled(every = "{payg.job.stale-close-interval}") + a Duration config property if the interval must stay tunable.
</details>
<details><summary><b>Transactions</b> (5)</summary>
- `app/proprietary/src/main/java/stirling/software/proprietary/config/AuditJpaConfig.java:6` - TODO: Migration required - Quarkus enables transaction management automatically (Narayana/JTA via quarkus-narayana-jta); the Spring @EnableTransactionManagement is not needed. Use jakarta.transaction.@Transactional on methods/beans as required. Scheduling is enabled on the application — no duplicate @EnableScheduling needed. JPA repositories are auto-discovered by Quarkus (no @EnableJpaRepositories needed).
- `app/saas/src/main/java/stirling/software/saas/ai/controller/AiCreateController.java:133` - TODO: Migration required - @Transactional(readOnly = true): jakarta.transaction.Transactional has no readOnly attribute; using a plain transaction.
- `app/saas/src/main/java/stirling/software/saas/ai/controller/AiCreateController.java:143` - TODO: Migration required - @Transactional(readOnly = true): jakarta.transaction.Transactional has no readOnly attribute; using a plain transaction.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:59` - TODO: Migration required - replaces Spring TransactionAspectSupport. Used to mark the current jakarta @Transactional transaction rollback-only without propagating the exception.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:123` - Caller-fixable failures (already-accepted, expired, email mismatch, etc.). Mark the transaction for rollback so anything the service did is reversed even though we don't propagate the exception out of the @Transactional method. TODO: Migration required - replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
- `app/proprietary/src/main/java/stirling/software/proprietary/config/AuditJpaConfig.java:6` - Quarkus enables transaction management automatically (Narayana/JTA via quarkus-narayana-jta); the Spring @EnableTransactionManagement is not needed. Use jakarta.transaction.@Transactional on methods/beans as required. Scheduling is enabled on the application — no duplicate @EnableScheduling needed. JPA repositories are auto-discovered by Quarkus (no @EnableJpaRepositories needed).
- `app/saas/src/main/java/stirling/software/saas/ai/controller/AiCreateController.java:133` - @Transactional(readOnly = true): jakarta.transaction.Transactional has no readOnly attribute; using a plain transaction.
- `app/saas/src/main/java/stirling/software/saas/ai/controller/AiCreateController.java:143` - @Transactional(readOnly = true): jakarta.transaction.Transactional has no readOnly attribute; using a plain transaction.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:59` - replaces Spring TransactionAspectSupport. Used to mark the current jakarta @Transactional transaction rollback-only without propagating the exception.
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:123` - Caller-fixable failures (already-accepted, expired, email mismatch, etc.). Mark the transaction for rollback so anything the service did is reversed even though we don't propagate the exception out of the @Transactional method. replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
</details>
<details><summary><b>Multipart / Resource abstractions</b> (10)</summary>
- `app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java:753` - TODO: Migration required - returns org.springframework.core.io.Resource, a public signature relied on by callers. Converting to InputStream/byte[]/java.nio would ripple to those call sites, so the Spring Resource type is retained for now.
- `app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java:766` - TODO: Migration required - returns org.springframework.core.io.Resource, a public signature relied on by callers. Converting to InputStream/byte[]/java.nio would ripple to those call sites, so the Spring Resource type is retained for now.
- `app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java:779` - TODO: Migration required - returns org.springframework.core.io.Resource, a public signature relied on by callers. Converting to InputStream/byte[]/java.nio would ripple to those call sites, so the Spring Resource type is retained for now.
- `app/common/src/main/java/stirling/software/common/model/MultipartFile.java:24` - service layer relies on (it exposes {@code org.jboss.resteasy.reactive.multipart.FileUpload} at the REST boundary instead). To avoid rewriting the public signatures of dozens of service and util methods across every module, this interface mirrors the subset of Spring's API that the codebase actually uses. Controllers adapt the inbound {@code FileUpload}/{@code byte[]} to one of the implementations ({@link stirling.software.common.model.multipart.ByteArrayMultipartFile}, {@link stirling.softwa...
- `app/common/src/main/java/stirling/software/common/util/misc/CustomColorReplaceStrategy.java:30` - TODO: Migration required - MultipartFile is the constructor parameter type that must match the parent ReplaceAndInvertColorStrategy(MultipartFile, ReplaceAndInvert) constructor (not in scope for this migration). There is no JAX-RS drop-in for this widely used public signature; retained until the parent and its callers are migrated together.
- `app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java:88` - MIGRATION (Spring -> JAX-RS): adapt the inbound multipart uploads to the migration shim MultipartFile so they can be passed to the existing service layer. TODO: Migration required - PipelineProcessor.generateInputFiles still declares the Spring org.springframework.web.multipart.MultipartFile[] parameter type. When that collaborator is migrated to stirling.software.common.model.MultipartFile[], this array type lines up. Until then this controller will not compile against the processor; the ada...
- `app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPdfToCbzRequest.java:30` - TODO: Migration required - controller binds this model via @BeanParam multipart. The 'fileInput' field is a raw FileUpload for form binding; the controller must adapt it to a stirling.software.common.model.MultipartFile via FileUploadMultipartFile.of(fileInput).
- `app/proprietary/src/main/java/stirling/software/proprietary/service/ByteHashFileIdStrategy.java:17` - TODO: Migration required - the FileIdStrategy interface (collaborator file) still imports org.springframework.web.multipart.MultipartFile; it must be switched to stirling.software.common.model.MultipartFile so this implementation's signature matches.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:91` - TODO: Migration required - storeFileResponse(...) still accepts Spring org.springframework.web.multipart.MultipartFile. Migrate FileStorageService to accept stirling.software.common.model.MultipartFile, then this wrapping is type-compatible.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:111` - TODO: Migration required - updateFileResponse(...) still accepts Spring MultipartFile; migrate FileStorageService to stirling.software.common.model.MultipartFile.
- `app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java:753` - returns org.springframework.core.io.Resource, a public signature relied on by callers. Converting to InputStream/byte[]/java.nio would ripple to those call sites, so the Spring Resource type is retained for now.
- `app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java:766` - returns org.springframework.core.io.Resource, a public signature relied on by callers. Converting to InputStream/byte[]/java.nio would ripple to those call sites, so the Spring Resource type is retained for now.
- `app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java:779` - returns org.springframework.core.io.Resource, a public signature relied on by callers. Converting to InputStream/byte[]/java.nio would ripple to those call sites, so the Spring Resource type is retained for now.
- `app/common/src/main/java/stirling/software/common/model/MultipartFile.java:24` - service layer relies on (it exposes {@code org.jboss.resteasy.reactive.multipart.FileUpload} at the REST boundary instead). To avoid rewriting the public signatures of dozens of service and util methods across every module, this interface mirrors the subset of Spring's API that the codebase actually uses. Controllers adapt the inbound {@code FileUpload}/{@code byte[]} to one of the implementations ({@link ...
- `app/common/src/main/java/stirling/software/common/util/misc/CustomColorReplaceStrategy.java:30` - MultipartFile is the constructor parameter type that must match the parent ReplaceAndInvertColorStrategy(MultipartFile, ReplaceAndInvert) constructor (not in scope for this migration). There is no JAX-RS drop-in for this widely used public signature; retained until the parent and its callers are migrated together.
- `app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java:88` - MIGRATION (Spring -> JAX-RS): adapt the inbound multipart uploads to the migration shim MultipartFile so they can be passed to the existing service layer. PipelineProcessor.generateInputFiles still declares the Spring org.springframework.web.multipart.MultipartFile[] parameter type. When that collaborator is migrated to stirling.software.common.model.MultipartFile[], this array type lines up. Until then this controller will not ...
- `app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPdfToCbzRequest.java:30` - controller binds this model via @BeanParam multipart. The 'fileInput' field is a raw FileUpload for form binding; the controller must adapt it to a stirling.software.common.model.MultipartFile via FileUploadMultipartFile.of(fileInput).
- `app/proprietary/src/main/java/stirling/software/proprietary/service/ByteHashFileIdStrategy.java:17` - the FileIdStrategy interface (collaborator file) still imports org.springframework.web.multipart.MultipartFile; it must be switched to stirling.software.common.model.MultipartFile so this implementation's signature matches.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:91` - storeFileResponse(...) still accepts Spring org.springframework.web.multipart.MultipartFile. Migrate FileStorageService to accept stirling.software.common.model.MultipartFile, then this wrapping is type-compatible.
- `app/proprietary/src/main/java/stirling/software/proprietary/storage/controller/FileStorageController.java:111` - updateFileResponse(...) still accepts Spring MultipartFile; migrate FileStorageService to stirling.software.common.model.MultipartFile.
</details>
<details><summary><b>Caching</b> (2)</summary>
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/CacheConfig.java:8` - TODO: Migration required - Spring's @EnableCaching + a programmatic CaffeineCacheManager @Bean has no direct Quarkus equivalent. Quarkus caching is annotation-driven (io.quarkus.cache.@CacheResult / @CacheInvalidate / @CacheName) and configured declaratively in application.properties, e.g.: quarkus.cache.caffeine."<cache-name>".maximum-size=1000 quarkus.cache.caffeine."<cache-name>".expire-after-write=<keyRetentionDays>D quarkus.cache.caffeine."<cache-name>".metrics-enabled=true # was .record...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPersistenceService.java:54` - TODO: Migration required - Spring's CacheManager/Cache("verifyingKeys") has no direct Quarkus-cache equivalent (io.quarkus.cache.Cache cannot enumerate its values). A directly-managed Caffeine cache preserves put/get/evict semantics.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/CacheConfig.java:8` - Spring's @EnableCaching + a programmatic CaffeineCacheManager @Bean has no direct Quarkus equivalent. Quarkus caching is annotation-driven (io.quarkus.cache.@CacheResult / @CacheInvalidate / @CacheName) and configured declaratively in application.properties, e.g.: quarkus.cache.caffeine."<cache-name>".maximum-size=1000 quarkus.cache.caffeine."<cache-name>".expire-after-write=<keyRetentionDays>D ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPersistenceService.java:54` - Spring's CacheManager/Cache("verifyingKeys") has no direct Quarkus-cache equivalent (io.quarkus.cache.Cache cannot enumerate its values). A directly-managed Caffeine cache preserves put/get/evict semantics.
</details>
<details><summary><b>Session management</b> (1)</summary>
- `app/proprietary/build.gradle:36` - REMOVED: spring-session-core - Quarkus has no Spring Session. Server-side session state (SessionPersistentRegistry, SessionRegistry) must be rewritten on Quarkus' HTTP session (quarkus-undertow servlet session) or a custom store. TODO: Migration required - port Spring Session usage (session registry / persistence).
- `app/proprietary/build.gradle:36` - REMOVED: spring-session-core - Quarkus has no Spring Session. Server-side session state (SessionPersistentRegistry, SessionRegistry) must be rewritten on Quarkus' HTTP session (quarkus-undertow servlet session) or a custom store. port Spring Session usage (session registry / persistence).
</details>
<details><summary><b>Other deferred migration work</b> (71)</summary>
- `app/common/build.gradle:79` - Jackson 3 (tools.jackson) - retained because ~100 files migrated to the Jackson 3 namespace under Spring Boot 4. Quarkus integrates Jackson 2 for REST bodies; Jackson 3 coexists here as a plain library so those files compile and can still build/parse JSON directly. api-scoped so downstream modules (core, proprietary, saas) that import tools.jackson inherit it. TODO: Migration required - converge the codebase on a single Jackson major version.
- `app/common/src/main/java/stirling/software/common/configuration/AppConfig.java:101` - MIGRATION: many beans inject tools.jackson.databind.ObjectMapper (Jackson 3, inherited from Spring Boot 4). Quarkus' container only produces a com.fasterxml.jackson (Jackson 2) ObjectMapper for REST (de)serialization, so the Jackson 3 type is an unsatisfied CDI dependency. This producer supplies a single application-scoped Jackson 3 mapper built the same way the codebase builds them ad hoc (JsonMapper.builder().build()). REST bodies still go through Quarkus' Jackson 2 mapper; this is only for...
- `app/common/src/main/java/stirling/software/common/model/io/Resource.java:17` - public method signatures across the codebase that accept or return {@code Resource}, this interface mirrors the subset of Spring's API the codebase actually uses ({@code getInputStream/exists/getFile/getFilename/contentLength/isFile}) together with the {@link FileSystemResource}, {@link InputStreamResource} and {@link ClassPathResource} implementations. Converting a file is then just an import swap. TODO: Migration required - longer term, prefer {@code java.nio.file.Path} / {@code InputStream...
- `app/common/src/main/java/stirling/software/common/service/InternalApiClient.java:273` - Resolve the port lazily so desktop mode dispatches to the actual bound port. TODO: Migration required - verify Quarkus exposes the bound port via config. Quarkus uses "quarkus.http.port" and, for random-port test/dev runs, "quarkus.http.test-port"; the old "local.server.port"/"server.port" keys came from Spring Boot's WebServerInitializedEvent.
- `app/common/src/main/java/stirling/software/common/service/JobQueue.java:29` - TODO: Migration required - the original class implemented Spring's SmartLifecycle, which has no direct Quarkus equivalent. start() is now driven by a StartupEvent observer and stop() by @PreDestroy. The SmartLifecycle phase/auto-startup ordering semantics (getPhase()==10) cannot be expressed in CDI; if precise startup/shutdown ordering relative to other beans is required, revisit using @Priority on the observer or @io.quarkus.runtime.Startup with an ordering strategy.
- `app/common/src/main/java/stirling/software/common/util/GeneralUtils.java:258` - ResourcePatternUtils} pattern resolver. The {@code ResourceLoader} parameter was removed. {@code file:} patterns are resolved with {@link java.nio.file.Files#list}; {@code classpath:} patterns are resolved via the classloader and only support directory resources that live on the filesystem. TODO: Migration required - {@code classpath:} resolution does not enumerate entries inside a packaged JAR. For uber-jar deployments, prefer serving these assets from {@code META-INF/resources/} or build a ...
- `app/common/src/main/java/stirling/software/common/util/SpringContextHolder.java:66` - TODO: Migration required - Spring looked up by bean name across all types; here we resolve a @Named CDI bean of Object.class. Verify named beans are registered with a matching @jakarta.inject.Named qualifier so this lookup resolves the intended bean.
- `app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java:78` - TODO: Migration required - profile auto-detection (former getActiveProfile / Spring setAdditionalProfiles) must be expressed via "quarkus.profile". The classpath-shape detection logic is retained below in getActiveProfile(); translate its result into the "quarkus.profile" system property (e.g. System.setProperty("quarkus.profile", ...)) before Quarkus.run if profile-based config layering is required.
- `app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java:171` - TODO: Migration required - the Spring "local.server.port" property exposed the actual runtime port (relevant for server.port=0 / "auto" port assignment). In Quarkus read the resolved port from config "quarkus.http.port" (or observe an HTTP-started event) and update serverPortStatic here. Falling back to the configured value for now.
- `app/core/src/main/java/stirling/software/SPDF/config/AppUpdateService.java:31` - MIGRATION: Spring's request-scoped boolean bean -> @Dependent. A CDI normal scope (@RequestScoped) requires a client proxy, which is impossible for a primitive producer ("Producer method for a normal scoped bean must not have a primitive type"). @Dependent recomputes the value at each injection point, the closest behaviour to per-request evaluation. TODO: Migration required - if true per-HTTP-request semantics are needed, wrap the value in a @RequestScoped holder object instead of producing a...
- `app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java:21` - TODO: Migration required - Spring @Order(Ordered.HIGHEST_PRECEDENCE + 1) controlled the relative order of this startup hook against other initializers. CDI StartupEvent observers have no portable total ordering; if a specific run-before/run-after relationship is required, use @Priority on the observer parameter or @Observes(during=...) and coordinate ordering across the migrated startup beans.
- `app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java:42` - TODO: Migration required - endpoint mapping was commented out in the original Spring source (the @PostMapping/@Operation were disabled), so this route remains intentionally inactive. The conversion below preserves the disabled state: routing annotations are kept commented. To enable, uncomment the JAX-RS annotations and provide a multipart-bound request. @POST @jakarta.ws.rs.Path("/print-file") @jakarta.ws.rs.Consumes(MediaType.MULTIPART_FORM_DATA) @io.swagger.v3.oas.annotations.Operation( su...
- `app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java:52` - server.servlet.context-path has no direct Quarkus equivalent (it maps to quarkus.http.root-path at build time). Kept as a configurable property so the index.html base href rewrite still works. TODO: Migration required - consider sourcing this from quarkus.http.root-path instead.
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:554` - Build the JSON body previously written directly to the servlet response when the client's Accept header could not be satisfied (Spring's {@code HttpMediaTypeNotAcceptableException}). TODO: Migration required - this path was triggered by Spring MVC content negotiation. Under Quarkus/JAX-RS the equivalent is {@code jakarta.ws.rs.NotAcceptableException}; a collaborator should register a mapper that returns this body with status 406 and Content-Type application/problem+json. The body-building log...
- `app/core/src/main/resources/application.properties:113` - ---- Jackson (was spring.jackson.*) ---------------------------------------------------------- spring.jackson.deserialization.fail-on-null-for-primitives=false TODO: Migration required - no Quarkus property for FAIL_ON_NULL_FOR_PRIMITIVES; register a CDI io.quarkus.jackson.ObjectMapperCustomizer that disables that DeserializationFeature.
- `app/core/src/main/resources/application.properties:132` - ---- External config files ------------------------------------------------------------------- TODO: Migration required - SPDFApplication injected external settings.yml / custom settings via spring.config.additional-location. Quarkus uses a different config-source mechanism (SmallRye Config / quarkus.config.locations). Port ConfigInitializer accordingly.
- `app/proprietary/build.gradle:96` - JDBC drivers via Quarkus extensions (wire into the Agroal datasource). NOTE: H2 is pinned to 2.3.232 because the on-disk file format is incompatible with 2.4.x and upgrading would break existing user databases. quarkus-jdbc-h2's BOM-managed H2 version may differ, so the explicit pin is forced below to preserve file compatibility. TODO: Migration required - verify the H2 version Quarkus resolves still reads 2.3.232 files.
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:114` - Only create the map once we know we'll use it TODO: Migration required - createBaseAuditData must accept InvocationContext (ctx) once AuditService is migrated off ProceedingJoinPoint.
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:124` - TODO: Migration required - addFileData must accept InvocationContext (ctx).
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:148` - TODO: Migration required - addMethodArguments must accept InvocationContext (ctx).
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:199` - TODO: Migration required - resolveEventType reads joinPoint.getTarget(); once AuditService is migrated it should use ctx.getTarget().getClass() instead.
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/ControllerAuditAspect.java:89` - TODO: Migration required - this single {@code @AroundInvoke} replaces the five Spring {@code @Around} advices (GET/POST/PUT/DELETE/PATCH + AutoJobPostMapping) and the static-resource {@code execution(...)} advice. Because CDI cannot inspect Spring/JAX-RS mapping annotations to derive the HTTP verb at bind time, the verb is resolved from the live request ({@link HttpServletRequest#getMethod()}); if the request is unavailable (non-web invocation) it falls back to POST to mirror the most common ...
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/ControllerAuditAspect.java:315` - Fallback: try JAX-RS @Path annotation on method/class; return empty string if not present TODO: Migration required - resolve path from jakarta.ws.rs.@Path on the declaring class and method once all controllers are fully on JAX-RS. The Spring fallback was removed.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/ClusterLicenseGate.java:20` - Runtime license gate for cluster mode. Cluster mode requires a SERVER or ENTERPRISE license; the SaaS flavor bypasses (no {@code runningProOrHigher} bean is published). The Valkey connection config {@code @DependsOn} this bean, so it runs before any Valkey bean is constructed. TODO: Migration required - Spring @DependsOn ordering relative to the Valkey connection config has no direct Quarkus equivalent. Ensure the Valkey/Redis bean either @Inject's this gate or that this verification still ru...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/ClusterNodeBootstrap.java:35` - Integer.MAX_VALUE} so Spring tore this bean down before {@code LettuceConnectionFactory} - deregister therefore ran while the Valkey connection was still alive. TODO: Migration required - Quarkus has no SmartLifecycle/getPhase shutdown-ordering equivalent. Startup now runs via @Observes StartupEvent and shutdown via @PreDestroy. If the Quarkus Redis/Valkey client is torn down before this bean's @PreDestroy, the deregister call may fail (it already tolerates that via TTL expiry). If strict ord...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:69` - TODO: Migration required - in Quarkus the RedisDataSource is produced by the quarkus-redis-client extension from quarkus.redis.* config rather than constructed here. This producer simply hands back the container-managed RedisDataSource so existing @Inject points keep compiling. The URL/TLS validation that used to build the LettuceConnectionFactory is still performed (and the boot handshake attempted) so misconfiguration fails fast.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:177` - Bound every backplane command. Without this a partitioned or slow Valkey would stall hot-path calls (e.g. JobController.guardNonOwner -> jobStore.get on each request); all backplane ops are non-blocking single commands, so a short timeout is safe. TODO: Migration required - propagate this to quarkus.redis.timeout=2s.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:191` - 10 x 3s = 30s boot-time retry. Auth failures (WRONGPASS/NOAUTH/NOPERM) short-circuit immediately; only transport errors get the loop. Package-private for testing. TODO: Migration required - this previously issued PING via a spring-data-redis RedisConnection. With Quarkus it should issue {@code ds.execute("PING")} (string command). The loop structure and auth short-circuit are retained; the actual ping call is stubbed so the file compiles until the RedisDataSource command surface is wired in.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:252` - TODO: Migration required - replace with ds.execute("PING").toString() (or the typed RedisDataSource command API) once the Quarkus command surface for the backplane is wired.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:302` - MIGRATION: Bucket4j's Lettuce ProxyManager (ValkeyRateLimitStore) needs a raw io.lettuce.core.RedisClient, which Quarkus' redis extension does not expose. Produce one from the same cluster.valkey.url the rest of the backplane uses so the injection point for AbstractRedisClient resolves. Only active when the Valkey backplane is selected. TODO: Migration required - propagate password/TLS auth from the parsed endpoint onto the RedisURI once cluster.valkey credentials handling is finalised.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyRateLimitStore.java:39` - TODO: Migration required - this previously received a spring-data-redis LettuceConnectionFactory (produced by the not-yet-migrated ValkeyConnectionConfiguration) and unwrapped its native io.lettuce.core.RedisClient. Bucket4j's Lettuce ProxyManager only needs that raw RedisClient. Once ValkeyConnectionConfiguration is migrated to a Quarkus producer (exposing a RedisClient or io.quarkus.redis.datasource.RedisDataSource), inject it here directly and drop the AbstractRedisClient unwrap below. The...
- `app/proprietary/src/main/java/stirling/software/proprietary/config/CustomAuditEventRepository.java:22` - TODO: Migration required - this class implemented Spring Boot Actuator's org.springframework.boot.actuate.audit.AuditEventRepository (with @Primary). Quarkus has no Actuator equivalent, so the interface and the org.springframework.boot.actuate.audit.AuditEvent type are gone. The write side has been ported to a plain CDI bean that accepts the audit data directly (see add(...) below). Whatever Spring code previously published AuditEvents to this repository must be updated to call this bean's ad...
- `app/proprietary/src/main/java/stirling/software/proprietary/config/CustomAuditEventRepository.java:90` - TODO: Migration required - repo.persist(...) depends on PersistentAuditEventRepository being migrated to a Quarkus PanacheRepository (save -> persist). Update this call once that collaborator is converted.
- `app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AiEngineController.java:77` - SSE stream timeout (ms), long enough for multi-gigabyte PDF workflows without completing out from under the executor. Derived from {@code aiEngine.streamTimeoutSeconds}. TODO: Migration required - the JAX-RS SSE API has no per-emitter timeout equivalent to Spring's {@code SseEmitter} constructor argument. Enforce this timeout against the background orchestration task (e.g. a scheduled cancellation / Future.get with timeout) if a hard cap is required; for now it only drives the timeout error f...
- `app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AuditDashboardController.java:68` - TODO: Migration required - PersistentAuditEventRepository is a collaborator that must be migrated to io.quarkus.hibernate.orm.panache.PanacheRepositoryBase<PersistentAuditEvent, Long>. Its paged finders should return io.quarkus.panache.common.PanacheQuery (or apply the Page/Sort built here) instead of org.springframework.data.domain.Page. The pagination request below is expressed with Panache Page/Sort; once the repository accepts these the .page(...)/.list()/.count()/.pageCount() calls used ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/McpServerController.java:112` - Spring's @ExceptionHandler(HttpMessageNotReadableException.class) wrapped malformed-JSON failures as a JSON-RPC Parse error. In JAX-RS this maps to a jakarta.ws.rs.ext.ExceptionMapper provider. TODO: Migration required - move this handling to a @Provider ExceptionMapper<...> (e.g. mapping the JSON deserialization exception thrown by the Jackson MessageBodyReader) returning HTTP 400 with JsonRpcResponse.failure(null, JsonRpcError.parseError("Request body is not valid JSON")). Kept here for ref...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpSecurityConfig.java:95` - TODO: Migration required - the following describe the original chain wiring so the Quarkus re-implementation can reproduce it faithfully. They are documented as notes rather than executable HttpSecurity DSL (which does not exist in Quarkus).
- `app/proprietary/src/main/java/stirling/software/proprietary/model/api/ai/AiWorkflowRequest.java:33` - TODO: Migration required - conversationHistory is a list of POJOs; RESTEasy has no form converter for AiConversationMessage. It must be received as a JSON form part (e.g. a String field parsed with ObjectMapper, or a @RestForm @PartType(APPLICATION_JSON) field) once the multipart contract for this endpoint is finalised.
- `app/proprietary/src/main/java/stirling/software/proprietary/model/api/audit/AuditDateExportRequest.java:27` - TODO: Migration required - Spring @DateTimeFormat(iso = ISO.DATE) removed; JAX-RS binds LocalDate via its default ISO-8601 (yyyy-MM-dd) ParamConverter, so ISO.DATE form values still bind. If a non-ISO format is ever needed, register a jakarta.ws.rs.ext.ParamConverter.
- `app/proprietary/src/main/java/stirling/software/proprietary/repository/PersistentAuditEventRepository.java:46` - --------------------------------------------------------------------- Basic paged queries TODO: Migration required - callers must adapt to the PanacheQuery return type (see class doc). ---------------------------------------------------------------------
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java:129` - TODO: Migration required - the Spring @ConditionalOnBooleanProperty(name = "premium.enabled") gate is not expressible on a private helper under CDI. The custom-database path is already guarded at runtime by the runningProOrHigher + datasource.enableCustomDatabase checks in dataSource(); if a separate premium.enabled toggle is still required, read it via org.eclipse.microprofile.config.Config (e.g. premium.enabled) inside dataSource() before calling this method.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java:16` - This configuration class used to provide the Spring JavaMailSender bean. After the Quarkus migration, mail sending is handled by Quarkus' built-in {@code io.quarkus.mailer.Mailer}, which is auto-provided by the quarkus-mailer extension and injected directly where needed (e.g. in EmailService). There is therefore no longer a producer method here. TODO: Migration required - the SMTP connection settings previously configured programmatically from {@link ApplicationProperties.Mail} (host, port, u...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/PasswordEncoderConfig.java:23` - TODO: Migration required - replace BCryptPasswordEncoder once a Quarkus-compatible BCrypt implementation is wired in (see class-level note).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:277` - Produces the persistent remember-me token repository. TODO: Migration required - {@link JPATokenRepositoryImpl} implements the Spring Security {@code PersistentTokenRepository} interface (collaborator not yet migrated). The remember-me feature itself has no Quarkus equivalent (see class javadoc); the repository is still produced so the persistence logic is available to the reimplementation. Producer return type narrowed to the concrete class to avoid importing the Spring interface here.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java:92` - Catches any messaging exception (e.g., invalid email address, SMTP server issues). TODO: Migration required - the Spring-specific org.springframework.mail.MailSendException ("Invalid Addresses" case) was previously handled separately. Once EmailService is migrated off Spring's JavaMailSender that branch can be reintroduced with the replacement exception type.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java:258` - TODO: Migration required - Spring's SecurityContextLogoutHandler has no Quarkus equivalent. Session/logout handling must be re-implemented via the migrated session registry (expire the current session) and/or quarkus auth config.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java:346` - TODO: Migration required - Spring's SecurityContextLogoutHandler has no Quarkus equivalent. Re-implement logout via the migrated session registry / quarkus auth config.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java:391` - TODO: Migration required - Spring's SecurityContextLogoutHandler has no Quarkus equivalent. Re-implement logout via the migrated session registry / quarkus auth config.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/enterprise/DatabaseControllerEnterprise.java:24` - TODO: Migration required - @Conditional(H2SQLCondition.class) had no direct Quarkus equivalent. H2SQLCondition is an org.springframework.context.annotation.Condition that inspects active profiles and datasource URL/type at bean-registration time. Quarkus has no equivalent for an arbitrary runtime Condition deciding whether to register a JAX-RS resource. Options: gate the endpoints with @io.quarkus.arc.lookup.LookupIfProperty / @io.quarkus.arc.profile.IfBuildProfile if the H2 check can be redu...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/database/H2SQLCondition.java:10` - TODO: Migration required - this was an org.springframework.context.annotation.Condition used via @Conditional(H2SQLCondition.class) to gate bean/controller registration at startup. Quarkus has no runtime @Conditional equivalent (@io.quarkus.arc.profile.IfBuildProfile / @LookupIfProperty are build-time/property-name based and cannot replicate this composite logic). The decision logic has been preserved as a runtime-evaluable CDI bean; callers that previously used @Conditional must inject this ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java:317` - TODO: Migration required - dropped catch for org.springframework.jdbc.datasource.init.CannotReadScriptException (Spring JDBC). Raw JDBC PreparedStatement.execute() only throws SQLException; the missing-file case is now reported via the SQLException branch above. Restore equivalent handling if a Quarkus/Hibernate script runner is introduced later.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java:511` - TODO: Migration required - dropped catch for org.springframework.jdbc.datasource.init.ScriptException (Spring JDBC). Raw JDBC PreparedStatement.execute() only throws SQLException; script errors are now logged via the SQLException branch above. Restore equivalent handling if a Quarkus/Hibernate script runner is introduced later.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPairCleanupService.java:29` - TODO: Migration required - Spring @ConditionalOnBooleanProperty("v2") dropped; the "v2" runtime toggle has no direct CDI equivalent. Guard activation via a runtime check or @io.quarkus.arc.lookup.LookupIfProperty / quarkus.scheduler config if this bean should be conditionally enabled.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java:82` - TODO: Migration required - org.springframework.context.MessageSource and LocaleContextHolder (Spring i18n) have no Quarkus equivalent on the classpath. Rebind to a Quarkus message bundle (io.quarkus.qute / @org.eclipse.microprofile.config or a jakarta.enterprise localization helper) and an explicit Locale source. The injected field is removed for now and getInvalidUsernameMessage() returns a constant fallback so the bean can be constructed; localization must be restored when the i18n layer is...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java:632` - TODO: Migration required - was messageSource.getMessage("invalidUsernameMessage", null, LocaleContextHolder.getLocale()). Spring's MessageSource / LocaleContextHolder are not on the Quarkus classpath; rebind to a Quarkus localization mechanism (message bundle + request Locale) and restore the localized lookup. Returning the message key as a fallback preserves behavior shape until i18n is ported.
- `app/proprietary/src/main/java/stirling/software/proprietary/workflow/dto/SignDocumentRequest.java:80` - TODO: Migration required - wetSignatures is a parsed list of POJOs populated by the controller/service from wetSignaturesData, not bound directly from the form; RESTEasy has no converter for WetSignatureMetadata, so it is intentionally left without @RestForm.
- `app/saas/src/main/java/stirling/software/saas/ai/service/AiCreateSessionService.java:39` - TODO: Migration required - Spring MVC RequestContextHolder/ServletRequestAttributes replaced with a CDI-injected request-scoped HttpServletRequest (quarkus-undertow). Wrapped in Instance so resolution outside an active HTTP request (e.g. scheduled/startup contexts) is a safe no-op.
- `app/saas/src/main/java/stirling/software/saas/config/SaasDataSourceConfig.java:12` - SaaS-profile Postgres datasource configuration. TODO: Migration required - datasource/JPA now configured via quarkus.datasource.* / quarkus.hibernate-orm.* in application.properties. The former Hikari-based DataSource bean (Postgres, @Primary over the OSS H2 default) translates to Quarkus config, e.g.: <pre> quarkus.datasource.db-kind=postgresql quarkus.datasource.username=${SPRING_DATASOURCE_USERNAME:postgres} quarkus.datasource.password=${SPRING_DATASOURCE_PASSWORD:} quarkus.datasource.jdbc...
- `app/saas/src/main/java/stirling/software/saas/config/SaasJpaConfig.java:10` - Previously registered the {@code :saas} module's entities and repositories with Spring Data JPA. TODO: Migration required - datasource/JPA now configured via quarkus.datasource.* / quarkus.hibernate-orm.* in application.properties. Entity scanning and repository discovery are automatic in Quarkus (Panache/Hibernate ORM), so the former @EnableJpaRepositories basePackages (stirling.software.saas.repository, .billing.repository, .ai.repository, .payg.repository) and @EntityScan packages (.model,...
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:131` - TODO: Migration required - replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:418` - TODO: Migration required - replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:426` - TODO: Migration required - replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:467` - TODO: Migration required - replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:475` - TODO: Migration required - replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
- `app/saas/src/main/java/stirling/software/saas/payg/lineage/LineagePruneScheduler.java:47` - TODO: Migration required - Spring 6-field cron "0 0 * * * *" (top of every hour) translated to Quartz cron "0 0 * ? * *" (day-of-month set to ? per Quartz day-of-week/day-of-month mutual-exclusion). Configurability is preserved via the {payg.lineage.prune-cron} config expression; set that property to a Quartz-syntax cron (default below) to override.
- `app/saas/src/main/java/stirling/software/saas/payg/policy/PolicyChangedEvent.java:12` - TODO: Migration required - was a Spring ApplicationEvent subclass. Converted to a plain POJO CDI event (no `extends ApplicationEvent`, no super(source) call). The `source` is retained as a plain field so the existing (Object source, String payload) constructor used by PricingPolicyService stays source-compatible.
- `app/saas/src/main/java/stirling/software/saas/payg/policy/PricingPolicyService.java:198` - TODO: Migration required - after-commit delivery is now expressed on the observer side via CDI's TransactionPhase.AFTER_SUCCESS (replacing the firing-side TransactionSynchronizationManager.registerSynchronization afterCommit hook). When no transaction is active (e.g. test paths calling write methods without a tx), CDI delivers the event immediately, matching the former else-branch behavior.
- `app/saas/src/main/java/stirling/software/saas/payg/policy/PricingPolicyService.java:227` - TODO: Migration required - was TransactionSynchronizationManager-driven after-commit dispatch; now a plain Event.fire() whose after-commit timing is enforced by the AFTER_SUCCESS observer phase on onPolicyChanged.
- `app/saas/src/main/java/stirling/software/saas/payg/test/PaygCucumberThrowController.java:65` - TODO: Migration required - declared return type was ResponseEntity<Void> so the AutoJobAspect @Around 500 reached the wire (see class javadoc). Verify the JAX-RS return-value handling of Response preserves the advice's 500 status under Quarkus.
- `app/saas/src/main/java/stirling/software/saas/service/SupabaseUserService.java:45` - TODO: Migration required - Spring Data save() did an upsert (merge); SupabaseUser uses an assigned UUID id and this path updates an existing row, so use EntityManager.merge to preserve update-or-insert semantics rather than Panache persist (INSERT-only).
- `build.gradle:275` - Jackson integration for JAX-RS bodies. Quarkus integrates Jackson 2 (com.fasterxml). TODO: Migration required - 100 files import tools.jackson (Jackson 3, from Spring Boot 4). Jackson 2 and 3 can coexist (different namespaces); the Jackson 3 dependency is retained in app/common so those files still compile, but REST (de)serialization goes through Quarkus' Jackson 2 ObjectMapper. Converge on one Jackson line later.
- `app/common/build.gradle:79` - Jackson 3 (tools.jackson) - retained because ~100 files migrated to the Jackson 3 namespace under Spring Boot 4. Quarkus integrates Jackson 2 for REST bodies; Jackson 3 coexists here as a plain library so those files compile and can still build/parse JSON directly. api-scoped so downstream modules (core, proprietary, saas) that import tools.jackson inherit it. converge the codebase on a single Jackson major version.
- `app/common/src/main/java/stirling/software/common/configuration/AppConfig.java:101` - MIGRATION: many beans inject tools.jackson.databind.ObjectMapper (Jackson 3, inherited from Spring Boot 4). Quarkus' container only produces a com.fasterxml.jackson (Jackson 2) ObjectMapper for REST (de)serialization, so the Jackson 3 type is an unsatisfied CDI dependency. This producer supplies a single application-scoped Jackson 3 mapper built the same way the codebase builds them ad hoc (JsonMapper.builder().build()). REST bodies still go through ...
- `app/common/src/main/java/stirling/software/common/model/io/Resource.java:17` - public method signatures across the codebase that accept or return {@code Resource}, this interface mirrors the subset of Spring's API the codebase actually uses ({@code getInputStream/exists/getFile/getFilename/contentLength/isFile}) together with the {@link FileSystemResource}, {@link InputStreamResource} and {@link ClassPathResource} implementations. Converting a file is then just an import swap. longer term, prefer {@code ...
- `app/common/src/main/java/stirling/software/common/service/InternalApiClient.java:273` - Resolve the port lazily so desktop mode dispatches to the actual bound port. verify Quarkus exposes the bound port via config. Quarkus uses "quarkus.http.port" and, for random-port test/dev runs, "quarkus.http.test-port"; the old "local.server.port"/"server.port" keys came from Spring Boot's WebServerInitializedEvent.
- `app/common/src/main/java/stirling/software/common/service/JobQueue.java:29` - the original class implemented Spring's SmartLifecycle, which has no direct Quarkus equivalent. start() is now driven by a StartupEvent observer and stop() by @PreDestroy. The SmartLifecycle phase/auto-startup ordering semantics (getPhase()==10) cannot be expressed in CDI; if precise startup/shutdown ordering relative to other beans is required, revisit using @Priority on the observer or @io.quarkus.runtime.Startup with an ...
- `app/common/src/main/java/stirling/software/common/util/GeneralUtils.java:258` - ResourcePatternUtils} pattern resolver. The {@code ResourceLoader} parameter was removed. {@code file:} patterns are resolved with {@link java.nio.file.Files#list}; {@code classpath:} patterns are resolved via the classloader and only support directory resources that live on the filesystem. {@code classpath:} resolution does not enumerate entries inside a packaged JAR. For uber-jar deployments, prefer serving these assets from ...
- `app/common/src/main/java/stirling/software/common/util/SpringContextHolder.java:66` - Spring looked up by bean name across all types; here we resolve a @Named CDI bean of Object.class. Verify named beans are registered with a matching @jakarta.inject.Named qualifier so this lookup resolves the intended bean.
- `app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java:78` - profile auto-detection (former getActiveProfile / Spring setAdditionalProfiles) must be expressed via "quarkus.profile". The classpath-shape detection logic is retained below in getActiveProfile(); translate its result into the "quarkus.profile" system property (e.g. System.setProperty("quarkus.profile", ...)) before Quarkus.run if profile-based config layering is required.
- `app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java:171` - the Spring "local.server.port" property exposed the actual runtime port (relevant for server.port=0 / "auto" port assignment). In Quarkus read the resolved port from config "quarkus.http.port" (or observe an HTTP-started event) and update serverPortStatic here. Falling back to the configured value for now.
- `app/core/src/main/java/stirling/software/SPDF/config/AppUpdateService.java:31` - MIGRATION: Spring's request-scoped boolean bean -> @Dependent. A CDI normal scope (@RequestScoped) requires a client proxy, which is impossible for a primitive producer ("Producer method for a normal scoped bean must not have a primitive type"). @Dependent recomputes the value at each injection point, the closest behaviour to per-request evaluation. if true per-HTTP-request semantics are needed, wrap the value in a ...
- `app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java:21` - Spring @Order(Ordered.HIGHEST_PRECEDENCE + 1) controlled the relative order of this startup hook against other initializers. CDI StartupEvent observers have no portable total ordering; if a specific run-before/run-after relationship is required, use @Priority on the observer parameter or @Observes(during=...) and coordinate ordering across the migrated startup beans.
- `app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java:42` - endpoint mapping was commented out in the original Spring source (the @PostMapping/@Operation were disabled), so this route remains intentionally inactive. The conversion below preserves the disabled state: routing annotations are kept commented. To enable, uncomment the JAX-RS annotations and provide a multipart-bound request. @POST @jakarta.ws.rs.Path("/print-file") @jakarta.ws.rs.Consumes(MediaType.MULTIPART_FORM_DATA) ...
- `app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java:52` - server.servlet.context-path has no direct Quarkus equivalent (it maps to quarkus.http.root-path at build time). Kept as a configurable property so the index.html base href rewrite still works. consider sourcing this from quarkus.http.root-path instead.
- `app/core/src/main/java/stirling/software/SPDF/exception/GlobalExceptionHandler.java:554` - Build the JSON body previously written directly to the servlet response when the client's Accept header could not be satisfied (Spring's {@code HttpMediaTypeNotAcceptableException}). this path was triggered by Spring MVC content negotiation. Under Quarkus/JAX-RS the equivalent is {@code jakarta.ws.rs.NotAcceptableException}; a collaborator should register a mapper that returns this body with status 406 and Content-Type ...
- `app/core/src/main/resources/application.properties:113` - ---- Jackson (was spring.jackson.*) ---------------------------------------------------------- spring.jackson.deserialization.fail-on-null-for-primitives=false no Quarkus property for FAIL_ON_NULL_FOR_PRIMITIVES; register a CDI io.quarkus.jackson.ObjectMapperCustomizer that disables that DeserializationFeature.
- `app/core/src/main/resources/application.properties:132` - ---- External config files ------------------------------------------------------------------- SPDFApplication injected external settings.yml / custom settings via spring.config.additional-location. Quarkus uses a different config-source mechanism (SmallRye Config / quarkus.config.locations). Port ConfigInitializer accordingly.
- `app/proprietary/build.gradle:96` - JDBC drivers via Quarkus extensions (wire into the Agroal datasource). NOTE: H2 is pinned to 2.3.232 because the on-disk file format is incompatible with 2.4.x and upgrading would break existing user databases. quarkus-jdbc-h2's BOM-managed H2 version may differ, so the explicit pin is forced below to preserve file compatibility. verify the H2 version Quarkus resolves still reads 2.3.232 files.
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:114` - Only create the map once we know we'll use it createBaseAuditData must accept InvocationContext (ctx) once AuditService is migrated off ProceedingJoinPoint.
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:124` - addFileData must accept InvocationContext (ctx).
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:148` - addMethodArguments must accept InvocationContext (ctx).
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java:199` - resolveEventType reads joinPoint.getTarget(); once AuditService is migrated it should use ctx.getTarget().getClass() instead.
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/ControllerAuditAspect.java:89` - this single {@code @AroundInvoke} replaces the five Spring {@code @Around} advice (GET/POST/PUT/DELETE/PATCH + AutoJobPostMapping) and the static-resource {@code execution(...)} advice. Because CDI cannot inspect Spring/JAX-RS mapping annotations to derive the HTTP verb at bind time, the verb is resolved from the live request ({@link HttpServletRequest#getMethod()}); if the request is unavailable (non-web invocation) it falls ...
- `app/proprietary/src/main/java/stirling/software/proprietary/audit/ControllerAuditAspect.java:315` - Fallback: try JAX-RS @Path annotation on method/class; return empty string if not present resolve path from jakarta.ws.rs.@Path on the declaring class and method once all controllers are fully on JAX-RS. The Spring fallback was removed.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/ClusterLicenseGate.java:20` - Runtime license gate for cluster mode. Cluster mode requires a SERVER or ENTERPRISE license; the SaaS flavor bypasses (no {@code runningProOrHigher} bean is published). The Valkey connection config {@code @DependsOn} this bean, so it runs before any Valkey bean is constructed. Spring @DependsOn ordering relative to the Valkey connection config has no direct Quarkus equivalent. Ensure the Valkey/Redis bean either @Inject's this ...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/ClusterNodeBootstrap.java:35` - Integer.MAX_VALUE} so Spring tore this bean down before {@code LettuceConnectionFactory} - deregister therefore ran while the Valkey connection was still alive. Quarkus has no SmartLifecycle/getPhase shutdown-ordering equivalent. Startup now runs via @Observes StartupEvent and shutdown via @PreDestroy. If the Quarkus Redis/Valkey client is torn down before this bean's @PreDestroy, the deregister call may fail (it already ...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:69` - in Quarkus the RedisDataSource is produced by the quarkus-redis-client extension from quarkus.redis.* config rather than constructed here. This producer simply hands back the container-managed RedisDataSource so existing @Inject points keep compiling. The URL/TLS validation that used to build the LettuceConnectionFactory is still performed (and the boot handshake attempted) so misconfiguration fails fast.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:177` - Bound every backplane command. Without this a partitioned or slow Valkey would stall hot-path calls (e.g. JobController.guardNonOwner -> jobStore.get on each request); all backplane ops are non-blocking single commands, so a short timeout is safe. propagate this to quarkus.redis.timeout=2s.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:191` - 10 x 3s = 30s boot-time retry. Auth failures (WRONGPASS/NOAUTH/NOPERM) short-circuit immediately; only transport errors get the loop. Package-private for testing. this previously issued PING via a spring-data-redis RedisConnection. With Quarkus it should issue {@code ds.execute("PING")} (string command). The loop structure and auth short-circuit are retained; the actual ping call is stubbed so the file compiles until the ...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:252` - replace with ds.execute("PING").toString() (or the typed RedisDataSource command API) once the Quarkus command surface for the backplane is wired.
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyConnectionConfiguration.java:302` - MIGRATION: Bucket4j's Lettuce ProxyManager (ValkeyRateLimitStore) needs a raw io.lettuce.core.RedisClient, which Quarkus' redis extension does not expose. Produce one from the same cluster.valkey.url the rest of the backplane uses so the injection point for AbstractRedisClient resolves. Only active when the Valkey backplane is selected. propagate password/TLS auth from the parsed endpoint onto the RedisURI once cluster.valkey ...
- `app/proprietary/src/main/java/stirling/software/proprietary/cluster/valkey/ValkeyRateLimitStore.java:39` - this previously received a spring-data-redis LettuceConnectionFactory (produced by the not-yet-migrated ValkeyConnectionConfiguration) and unwrapped its native io.lettuce.core.RedisClient. Bucket4j's Lettuce ProxyManager only needs that raw RedisClient. Once ValkeyConnectionConfiguration is migrated to a Quarkus producer (exposing a RedisClient or io.quarkus.redis.datasource.RedisDataSource), inject it here directly and drop the ...
- `app/proprietary/src/main/java/stirling/software/proprietary/config/CustomAuditEventRepository.java:22` - this class implemented Spring Boot Actuator's org.springframework.boot.actuate.audit.AuditEventRepository (with @Primary). Quarkus has no Actuator equivalent, so the interface and the org.springframework.boot.actuate.audit.AuditEvent type are gone. The write side has been ported to a plain CDI bean that accepts the audit data directly (see add(...) below). Whatever Spring code previously published AuditEvents to this repository ...
- `app/proprietary/src/main/java/stirling/software/proprietary/config/CustomAuditEventRepository.java:90` - repo.persist(...) depends on PersistentAuditEventRepository being migrated to a Quarkus PanacheRepository (save -> persist). Update this call once that collaborator is converted.
- `app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AiEngineController.java:77` - SSE stream timeout (ms), long enough for multi-gigabyte PDF workflows without completing out from under the executor. Derived from {@code aiEngine.streamTimeoutSeconds}. the JAX-RS SSE API has no per-emitter timeout equivalent to Spring's {@code SseEmitter} constructor argument. Enforce this timeout against the background orchestration task (e.g. a scheduled cancellation / Future.get with timeout) if a hard cap is required; for ...
- `app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AuditDashboardController.java:68` - PersistentAuditEventRepository is a collaborator that must be migrated to io.quarkus.hibernate.orm.panache.PanacheRepositoryBase<PersistentAuditEvent, Long>. Its paged finders should return io.quarkus.panache.common.PanacheQuery (or apply the Page/Sort built here) instead of org.springframework.data.domain.Page. The pagination request below is expressed with Panache Page/Sort; once the repository accepts these the ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/McpServerController.java:112` - Spring's @ExceptionHandler(HttpMessageNotReadableException.class) wrapped malformed-JSON failures as a JSON-RPC Parse error. In JAX-RS this maps to a jakarta.ws.rs.ext.ExceptionMapper provider. move this handling to a @Provider ExceptionMapper<...> (e.g. mapping the JSON deserialization exception thrown by the Jackson MessageBodyReader) returning HTTP 400 with JsonRpcResponse.failure(null, JsonRpcError.parseError("Request body ...
- `app/proprietary/src/main/java/stirling/software/proprietary/mcp/security/McpSecurityConfig.java:95` - the following describe the original chain wiring so the Quarkus re-implementation can reproduce it faithfully. They are documented as notes rather than executable HttpSecurity DSL (which does not exist in Quarkus).
- `app/proprietary/src/main/java/stirling/software/proprietary/model/api/ai/AiWorkflowRequest.java:33` - conversationHistory is a list of POJOs; RESTEasy has no form converter for AiConversationMessage. It must be received as a JSON form part (e.g. a String field parsed with ObjectMapper, or a @RestForm @PartType(APPLICATION_JSON) field) once the multipart contract for this endpoint is finalised.
- `app/proprietary/src/main/java/stirling/software/proprietary/model/api/audit/AuditDateExportRequest.java:27` - Spring @DateTimeFormat(iso = ISO.DATE) removed; JAX-RS binds LocalDate via its default ISO-8601 (yyyy-MM-dd) ParamConverter, so ISO.DATE form values still bind. If a non-ISO format is ever needed, register a jakarta.ws.rs.ext.ParamConverter.
- `app/proprietary/src/main/java/stirling/software/proprietary/repository/PersistentAuditEventRepository.java:46` - --------------------------------------------------------------------- Basic paged queries callers must adapt to the PanacheQuery return type (see class doc). ---------------------------------------------------------------------
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java:129` - the Spring @ConditionalOnBooleanProperty(name = "premium.enabled") gate is not expressible on a private helper under CDI. The custom-database path is already guarded at runtime by the runningProOrHigher + datasource.enableCustomDatabase checks in dataSource(); if a separate premium.enabled toggle is still required, read it via org.eclipse.microprofile.config.Config (e.g. premium.enabled) inside dataSource() before calling this ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java:16` - This configuration class used to provide the Spring JavaMailSender bean. After the Quarkus migration, mail sending is handled by Quarkus' built-in {@code io.quarkus.mailer.Mailer}, which is auto-provided by the quarkus-mailer extension and injected directly where needed (e.g. in EmailService). There is therefore no longer a producer method here. the SMTP connection settings previously configured programmatically from {@link ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/PasswordEncoderConfig.java:23` - replace BCryptPasswordEncoder once a Quarkus-compatible BCrypt implementation is wired in (see class-level note).
- `app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java:277` - Produces the persistent remember-me token repository. {@link JPATokenRepositoryImpl} implements the Spring Security {@code PersistentTokenRepository} interface (collaborator not yet migrated). The remember-me feature itself has no Quarkus equivalent (see class javadoc); the repository is still produced so the persistence logic is available to the reimplementation. Producer return type narrowed to the concrete class to avoid ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java:92` - Catches any messaging exception (e.g., invalid email address, SMTP server issues). the Spring-specific org.springframework.mail.MailSendException ("Invalid Addresses" case) was previously handled separately. Once EmailService is migrated off Spring's JavaMailSender that branch can be reintroduced with the replacement exception type.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java:258` - Spring's SecurityContextLogoutHandler has no Quarkus equivalent. Session/logout handling must be re-implemented via the migrated session registry (expire the current session) and/or quarkus auth config.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java:346` - Spring's SecurityContextLogoutHandler has no Quarkus equivalent. Re-implement logout via the migrated session registry / quarkus auth config.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java:391` - Spring's SecurityContextLogoutHandler has no Quarkus equivalent. Re-implement logout via the migrated session registry / quarkus auth config.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/enterprise/DatabaseControllerEnterprise.java:24` - @Conditional(H2SQLCondition.class) had no direct Quarkus equivalent. H2SQLCondition is an org.springframework.context.annotation.Condition that inspects active profiles and datasource URL/type at bean-registration time. Quarkus has no equivalent for an arbitrary runtime Condition deciding whether to register a JAX-RS resource. Options: gate the endpoints with @io.quarkus.arc.lookup.LookupIfProperty / ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/database/H2SQLCondition.java:10` - this was an org.springframework.context.annotation.Condition used via @Conditional(H2SQLCondition.class) to gate bean/controller registration at startup. Quarkus has no runtime @Conditional equivalent (@io.quarkus.arc.profile.IfBuildProfile / @LookupIfProperty are build-time/property-name based and cannot replicate this composite logic). The decision logic has been preserved as a runtime-evaluable CDI bean; callers that ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java:317` - dropped catch for org.springframework.jdbc.datasource.init.CannotReadScriptException (Spring JDBC). Raw JDBC PreparedStatement.execute() only throws SQLException; the missing-file case is now reported via the SQLException branch above. Restore equivalent handling if a Quarkus/Hibernate script runner is introduced later.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java:511` - dropped catch for org.springframework.jdbc.datasource.init.ScriptException (Spring JDBC). Raw JDBC PreparedStatement.execute() only throws SQLException; script errors are now logged via the SQLException branch above. Restore equivalent handling if a Quarkus/Hibernate script runner is introduced later.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPairCleanupService.java:29` - Spring @ConditionalOnBooleanProperty("v2") dropped; the "v2" runtime toggle has no direct CDI equivalent. Guard activation via a runtime check or @io.quarkus.arc.lookup.LookupIfProperty / quarkus.scheduler config if this bean should be conditionally enabled.
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java:82` - org.springframework.context.MessageSource and LocaleContextHolder (Spring i18n) have no Quarkus equivalent on the classpath. Rebind to a Quarkus message bundle (io.quarkus.qute / @org.eclipse.microprofile.config or a jakarta.enterprise localization helper) and an explicit Locale source. The injected field is removed for now and getInvalidUsernameMessage() returns a constant fallback so the bean can be constructed; localization ...
- `app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java:632` - was messageSource.getMessage("invalidUsernameMessage", null, LocaleContextHolder.getLocale()). Spring's MessageSource / LocaleContextHolder are not on the Quarkus classpath; rebind to a Quarkus localization mechanism (message bundle + request Locale) and restore the localized lookup. Returning the message key as a fallback preserves behavior shape until i18n is ported.
- `app/proprietary/src/main/java/stirling/software/proprietary/workflow/dto/SignDocumentRequest.java:80` - wetSignatures is a parsed list of POJOs populated by the controller/service from wetSignaturesData, not bound directly from the form; RESTEasy has no converter for WetSignatureMetadata, so it is intentionally left without @RestForm.
- `app/saas/src/main/java/stirling/software/saas/ai/service/AiCreateSessionService.java:39` - Spring MVC RequestContextHolder/ServletRequestAttributes replaced with a CDI-injected request-scoped HttpServletRequest (quarkus-undertow). Wrapped in Instance so resolution outside an active HTTP request (e.g. scheduled/startup contexts) is a safe no-op.
- `app/saas/src/main/java/stirling/software/saas/config/SaasDataSourceConfig.java:12` - SaaS-profile Postgres datasource configuration. datasource/JPA now configured via quarkus.datasource.* / quarkus.hibernate-orm.* in application.properties. The former Hikari-based DataSource bean (Postgres, @Primary over the OSS H2 default) translates to Quarkus config, e.g.: <pre> quarkus.datasource.db-kind=postgresql quarkus.datasource.username=${SPRING_DATASOURCE_USERNAME:postgres} ...
- `app/saas/src/main/java/stirling/software/saas/config/SaasJpaConfig.java:10` - Previously registered the {@code :saas} module's entities and repositories with Spring Data JPA. datasource/JPA now configured via quarkus.datasource.* / quarkus.hibernate-orm.* in application.properties. Entity scanning and repository discovery are automatic in Quarkus (Panache/Hibernate ORM), so the former @EnableJpaRepositories basePackages (stirling.software.saas.repository, .billing.repository, .ai.repository ...
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:131` - replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:418` - replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:426` - replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:467` - replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
- `app/saas/src/main/java/stirling/software/saas/controller/SaasTeamController.java:475` - replace Spring TransactionAspectSupport rollback-only with jakarta TransactionSynchronizationRegistry.setRollbackOnly() (injected).
- `app/saas/src/main/java/stirling/software/saas/payg/lineage/LineagePruneScheduler.java:47` - Spring 6-field cron "0 0 * * * *" (top of every hour) translated to Quartz cron "0 0 * ? * *" (day-of-month set to ? per Quartz day-of-week/day-of-month mutual-exclusion). Configurability is preserved via the {payg.lineage.prune-cron} config expression; set that property to a Quartz-syntax cron (default below) to override.
- `app/saas/src/main/java/stirling/software/saas/payg/policy/PolicyChangedEvent.java:12` - was a Spring ApplicationEvent subclass. Converted to a plain POJO CDI event (no `extends ApplicationEvent`, no super(source) call). The `source` is retained as a plain field so the existing (Object source, String payload) constructor used by PricingPolicyService stays source-compatible.
- `app/saas/src/main/java/stirling/software/saas/payg/policy/PricingPolicyService.java:198` - after-commit delivery is now expressed on the observer side via CDI's TransactionPhase.AFTER_SUCCESS (replacing the firing-side TransactionSynchronizationManager.registerSynchronization afterCommit hook). When no transaction is active (e.g. test paths calling write methods without a tx), CDI delivers the event immediately, matching the former else-branch behavior.
- `app/saas/src/main/java/stirling/software/saas/payg/policy/PricingPolicyService.java:227` - was TransactionSynchronizationManager-driven after-commit dispatch; now a plain Event.fire() whose after-commit timing is enforced by the AFTER_SUCCESS observer phase on onPolicyChanged.
- `app/saas/src/main/java/stirling/software/saas/payg/test/PaygCucumberThrowController.java:65` - declared return type was ResponseEntity<Void> so the AutoJobAspect @Around 500 reached the wire (see class javadoc). Verify the JAX-RS return-value handling of Response preserves the advice's 500 status under Quarkus.
- `app/saas/src/main/java/stirling/software/saas/service/SupabaseUserService.java:45` - Spring Data save() did an upsert (merge); SupabaseUser uses an assigned UUID id and this path updates an existing row, so use EntityManager.merge to preserve update-or-insert semantics rather than Panache persist (INSERT-only).
- `build.gradle:275` - Jackson integration for JAX-RS bodies. Quarkus integrates Jackson 2 (com.fasterxml). 100 files import tools.jackson (Jackson 3, from Spring Boot 4). Jackson 2 and 3 can coexist (different namespaces); the Jackson 3 dependency is retained in app/common so those files still compile, but REST (de)serialization goes through Quarkus' Jackson 2 ObjectMapper. Converge on one Jackson line later.
</details>