Skip to content
Flag of Europe
Made in the European Union · Independently built · Released under EUPL 1.2

00.60.00

Release date: 2026-05-14 Previous release: 00.51.00 Maven coordinates (parent): com.svenruppert:security-for-flow-parent:00.60.00

Closes the Konzept-V00.60 milestone. Every one of the seven security-core concept points (PasswordHasher, SecurityAuditService, LoginAttemptPolicy, SessionPolicy, AuthorizationService role↔permission mapping, LogoutService, ActionAuthorizationService) ships as a stable SPI with a default implementation, audit hooks, and adapter wiring. No breaking API change for code using the 00.51 contracts; one internal package move is noted below.

Highlights

  • 8 → 10 Maven modules with a fourth adapter and its demo
  • security-standalone (new) — plain-Java / desktop / CLI adapter: ThreadLocalSubjectStore, StandaloneLoginFlow<T, U>, Secured.wrap(Interface, impl) (JDK Dynamic Proxy), Secured.requireAllowed(Class, methodName) for callbacks. See Standalone Integration.
  • demo-standalone (new) — interactive library-borrowing CLI with three seeded users showing role-based + permission-based access.
  • Audit pipelineSecurityAuditService with publish/query, 16 sealed AuditEvent record variants, AuditSink contract, RingBufferAuditSink + LoggingAuditSink + DefaultCompositeAuditService.
  • LoginAttemptPolicy SPI with sealed LoginAttemptDecision = Allowed | LockedOut(Duration remaining, int failedAttempts).
  • SessionPolicy SPI with lifecycle hooks (onLogin, beforeNavigation, onLogout) and a pure-query evaluate(SessionMetadata) → SessionPolicyDecision (Active | IdleTimeout | AbsoluteLifetimeExceeded).
  • B3 — session-id rotation after login: LoginView honours SessionDecision.Invalidate("RotationAfterLogin") via VaadinService.reinitializeSession(...). SessionInvalidated audit event is emitted with the old session id.
  • LogoutService API rewritelogout(SubjectId, LogoutScope) with LogoutScope = CurrentSession | AllSessionsOfSubject. Adapter configuration (targetRoute, closeVaadinSession, invalidateHttpSession) lives on the VaadinLogoutService constructor.
  • ActionAuthorizationService<U> SPI with ActionPermission record. Default emits ActionDenied audit on denial.
  • Bootstrap auditingBootstrapAdminCreated / BootstrapTokenRejected(reason) from every emit path.
  • SecurityServiceResolver completeness — uniform strict / find…() / set…() triple for every cross-cutting service.
  • Vaadin Browserless Testing wired in security-vaadin and both Vaadin demos (free since Vaadin 25.1). Real adapter-test suite — no TestBench, no Karibu.
  • Mutation coverage lifted in every library module, with two new modules entering the table.

Module structure

ModuleArtifactPurpose
security-coresecurity-coreGeneric, framework-neutral security concepts and decision logic
security-vaadinsecurity-vaadinVaadin Flow adapter (navigation, listener, session, logout)
security-restsecurity-restFramework-light REST adapter (no Spring, no Jakarta Security)
security-standalonesecurity-standalonePlain-Java / desktop / CLI adapter — ThreadLocal subject + dynamic-proxy enforcement
demo-rest-shareddemo-rest-sharedTransport-level constants + tiny JSON helper
demo-vaadindemo-vaadinSingle-JVM Vaadin reference (WAR)
demo-restdemo-restREST reference (JAR) — JDK HttpServer
demo-vaadin-rest-clientdemo-vaadin-rest-clientVaadin UI consumes a separate REST backend
demo-standalonedemo-standaloneInteractive CLI library-borrowing demo

Dependency rules unchanged: security-core has no project deps; the three adapter modules never depend on each other; demos depend only on the core + their adapter.

Mutation coverage

Module00.51.0000.60.00
security-core86 %79 % ¹
security-vaadin79 %90 %
security-rest97 %95 %
security-standalone98 % (new)
demo-standalone86 % (new)
demo-vaadin70 % (new)
demo-rest49 % (new)
demo-vaadin-rest-client10 % (new)

¹ The 00.51 measurement was scoped narrower than the 00.60 surface (which now includes the audit pipeline, LoginAttemptPolicy, SessionPolicy, ActionAuthorizationService and the refactored LogoutService). Absolute killed-mutant count rose; the percentage is not directly comparable.

Migration from 00.51.00

One breaking package move plus opt-in new SPIs.

Package move — bootstrap.PasswordHash*authentication.PasswordHash*

PasswordHash, PasswordHasher, Pbkdf2PasswordHasher moved from com.svenruppert.vaadin.security.bootstrap to com.svenruppert.vaadin.security.authentication. Contracts unchanged.

// 00.51
import com.svenruppert.vaadin.security.bootstrap.PasswordHasher;
import com.svenruppert.vaadin.security.bootstrap.Pbkdf2PasswordHasher;

// 00.60
import com.svenruppert.vaadin.security.authentication.PasswordHasher;
import com.svenruppert.vaadin.security.authentication.Pbkdf2PasswordHasher;

Update META-INF/services/com.svenruppert.vaadin.security.bootstrap.PasswordHasher to META-INF/services/com.svenruppert.vaadin.security.authentication.PasswordHasher.

LogoutService API rewrite

00.51 had logout(LogoutContext); 00.60 has logout(SubjectId, LogoutScope) with LogoutScope.CurrentSession or LogoutScope.AllSessionsOfSubject. Adapter configuration (targetRoute, closeVaadinSession, invalidateHttpSession) now lives on the VaadinLogoutService constructor.

LogoutService logoutService = new VaadinLogoutService<>(
    SubjectStores.subjectStore(), MyUser.class,
    new DefaultVaadinLogoutGateway(),
    "/login", true, true);

logoutService.logout(SubjectId.of(String.valueOf(user.id())),
                     LogoutScope.CurrentSession);

Opt-in new SPIs

Existing applications keep working without any of these. Wire them in only when you need them:

  • SecurityAuditService
  • LoginAttemptPolicy
  • SessionPolicy (e.g. TimeoutSessionPolicy)
  • ActionAuthorizationService
  • LogoutService (e.g. VaadinLogoutService)

Build

  • Java 26 (sealed types, records, pattern matching)
  • Vaadin 25.1.1 (vaadin-core, no Hilla)
  • Jetty 12.1.8 EE11 for the Vaadin demos
  • Maven 3.9.9+
  • mvn clean install builds all 10 modules; library javadocs build clean.