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 pipeline —
SecurityAuditServicewithpublish/query, 16 sealedAuditEventrecord variants,AuditSinkcontract,RingBufferAuditSink+LoggingAuditSink+DefaultCompositeAuditService. LoginAttemptPolicySPI with sealedLoginAttemptDecision = Allowed | LockedOut(Duration remaining, int failedAttempts).SessionPolicySPI with lifecycle hooks (onLogin,beforeNavigation,onLogout) and a pure-queryevaluate(SessionMetadata) → SessionPolicyDecision(Active | IdleTimeout | AbsoluteLifetimeExceeded).- B3 — session-id rotation after login:
LoginViewhonoursSessionDecision.Invalidate("RotationAfterLogin")viaVaadinService.reinitializeSession(...).SessionInvalidatedaudit event is emitted with the old session id. LogoutServiceAPI rewrite —logout(SubjectId, LogoutScope)withLogoutScope = CurrentSession | AllSessionsOfSubject. Adapter configuration (targetRoute,closeVaadinSession,invalidateHttpSession) lives on theVaadinLogoutServiceconstructor.ActionAuthorizationService<U>SPI withActionPermissionrecord. Default emitsActionDeniedaudit on denial.- Bootstrap auditing —
BootstrapAdminCreated/BootstrapTokenRejected(reason)from every emit path. SecurityServiceResolvercompleteness — uniform strict /find…()/set…()triple for every cross-cutting service.- Vaadin Browserless Testing wired in
security-vaadinand 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
| Module | Artifact | Purpose |
|---|---|---|
security-core | security-core | Generic, framework-neutral security concepts and decision logic |
security-vaadin | security-vaadin | Vaadin Flow adapter (navigation, listener, session, logout) |
security-rest | security-rest | Framework-light REST adapter (no Spring, no Jakarta Security) |
security-standalone | security-standalone | Plain-Java / desktop / CLI adapter — ThreadLocal subject + dynamic-proxy enforcement |
demo-rest-shared | demo-rest-shared | Transport-level constants + tiny JSON helper |
demo-vaadin | demo-vaadin | Single-JVM Vaadin reference (WAR) |
demo-rest | demo-rest | REST reference (JAR) — JDK HttpServer |
demo-vaadin-rest-client | demo-vaadin-rest-client | Vaadin UI consumes a separate REST backend |
demo-standalone | demo-standalone | Interactive 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
| Module | 00.51.00 | 00.60.00 |
|---|---|---|
security-core | 86 % | 79 % ¹ |
security-vaadin | 79 % | 90 % |
security-rest | 97 % | 95 % |
security-standalone | — | 98 % (new) |
demo-standalone | — | 86 % (new) |
demo-vaadin | — | 70 % (new) |
demo-rest | — | 49 % (new) |
demo-vaadin-rest-client | — | 10 % (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:
SecurityAuditServiceLoginAttemptPolicySessionPolicy(e.g.TimeoutSessionPolicy)ActionAuthorizationServiceLogoutService(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 installbuilds all 10 modules; library javadocs build clean.