First named cut of the template. Bundles the security stack migration to jSentinel V00.74.00, the design-system + theming overhaul, the i18n rewrite, the storage-paths/test-isolation pass, the fail-fast bootstrap, the HIBP password leak check and the persistent drift-detection store.
- Bumped to jSentinel V00.74.00 (
com.svenruppert.jsentinel:*), up from V00.73.00. Surfaces the new Token-Propagation API (TokenCredentialStore,BearerToken/OidcAccessToken/RefreshToken/ApiKey,OutboundTokenStrategy,@PropagateToken) — theVaadinSessionTokenCredentialStoreis wired by default and theSecurityFeaturesViewcard panel documents the surface. BootstrapExtensionSPI splits the wiring into three additive layers —DefaultBootstrapExtension(order 0),PersistenceBootstrapExtension(order 10) andHardeningBootstrapExtension(order 20). Each layer contributes to.audit(...) / .sessions(...) / .credentials(...) / .policies(...)independently, picked up viaServiceLoaderat service init.- Restructured the
com.svenruppert.flow.securitypackage into focused sub-packages:model,roles,permissions,services,bootstrap,storage. - Typed permission catalog:
app:view,audit:read,admin:sessions,admin:roles(AppPermission). - Hybrid SPI registration:
@JSentinelAutoService(annotation processor) forAppAuthenticationServiceandAppAuthorizationService; hand-writtenMETA-INF/servicesfiles forAccessEvaluator,LoginListener,BootstrapExtension,JSentinelVersionStore,SubjectIdResolver, andVaadinServiceInitListener. - Eclipse-Store persistence:
EclipseStoreJSentinelStorageopens atapp.storage.dir/jsentinel(default./data/jsentinel). User directory, session store, audit ring buffer and the drift-detection version counter all share that backend.JSentinelStorageProviderexposes a lazy singleton + asetStorage(...)test seam; a shutdown hook closes the storage cleanly on JVM exit. - First-admin bootstrap via
BootstrapWiring+SetupView— a one-time token (bootstrap.tokenin the storage dir, validityPT24H) gates the initial admin creation. Username pattern[A-Za-z0-9._-](1–64 chars); password policy minimum 12 chars. - Argon2id password hashing (BouncyCastle modern profile)
replaces PBKDF2. Legacy PBKDF2 hashes still verify and auto-rehash
on next successful login via the
RehashDecisionEngine. - HIBP password leak check (
PasswordPreflight) — k-anonymity range API call againstapi.pwnedpasswords.com. Only the first 5 SHA-1 hex chars leave the JVM. Fail-open on network errors (CWE-359), opt-in viaapp.hibp.enabled(defaulttruein production; Surefire sets it tofalseso tests skip the network call). - Phase-4c drift detection — role mutations in
AdminRolesViewcallVersionBumper.bump(user)to increment the per-subjectJSentinelVersion;JSentinelVersionEnforcerListenerreroutes the affected session to/loginon the next request.PersistentJSentinelVersionStoreProvideradapts the Eclipse-Store-backedJSentinelVersionStoreforServiceLoaderso the version counter survives JVM restarts. - Fail-fast bootstrap —
JSentinelBootstrapInitListenerthrowsIllegalStateExceptionwith a diagnosis message whenAuthenticationServiceorAuthorizationServiceis absent, instead of silently no-opping. Misconfigured wiring surfaces at startup, not at the first login attempt. - Lazy
UserDirectoryProvider— Initialization-on-Demand Holder refactor: the persistent directory opens on first access, not at classload time. Tests that swap the directory before any access still win; SpotBugsMS_EXPOSE_REPsuppression dropped because the field is no longer eagerly exposed. AppStoragePaths— single source of truth for all storage locations (frameworkStorageDir,userDirectoryDir,bootstrapTokenFile). Driven by-Dapp.storage.dirso Surefire redirects tests totarget/test-dataand never touches the repo-rooted./data/tree.- Brute-force protection:
AppAuthenticationServiceconsultsLoginAttemptPolicyfor throttling and records success / failure on every login attempt. - Audit pipeline:
JSentinelAuditService(Eclipse-Store-backed) receivesLoginSucceeded,LoginFailed,LogoutPerformed,SessionCreated,SessionInvalidated,RoleAssigned,RoleRevoked,UserCreated,UserDeleted,SessionStaleevents. - Logout goes through
VaadinLogoutService— clears theSubjectStore, closes the Vaadin session, invalidates the HTTP session, redirects to/login.
MainLayout— AppLayout shell carrying the brand mark, role-gated drawer entries and the locale + theme + auth-action switchers in the navbar. Drawer entries useSecuredUi.link(...).requiresPermission(...).hideWhenDenied()so admin entries vanish for non-privileged subjects.SecurityFeaturesView— public landing page that documents the security stack as 11 feature cards (audit, sessions, drift detection, Argon2id hashing, HIBP, token propagation V00.74, …) plus a three-row table showing the BootstrapExtension chain (Default / Persistence / Hardening) and a per-layer status row.PushDemoView— atmos / observer /@Pushgrid showcasing all three Vaadin push styles inside the new layout.AppLoginView— adds an Enter-key login shortcut viaShortcuts.addShortcutListener+ComponentUtil.fireEvent, records aSessionRecordon success, and forwards to/setupwhen the bootstrap state isBOOTSTRAP_REQUIRED.SetupView(@Route("setup")) — initial-admin form; consumes the bootstrap token and the chosen username/password throughPasswordPreflight(local blocklist + HIBP) before handing off toInitialAdminBootstrapService.createInitialAdmin(...).AuditView(@RequiresPermission("audit:read")) — renders the audit feed as a sortable grid.SessionsView(@RequiresPermission("admin:sessions")) — extends the framework'sSessionManagementViewover the persistentSessionStore.AdminRolesView(@RequiresPermission("admin:roles")) — list / create / delete users, assign / revoke roles. Every mutation publishes an audit event and callsVersionBumper.bump(user).AboutView,YoutubeViewrewired to useMainLayoutas parent and the newrolespackage (@VisibleFor(AuthorizationRole.USER)).
- Custom
my-themeLumo theme with brand tokens, plus dark and jSentinel variants selectable through theThemeSwitcherin the navbar (preference persists per Vaadin session viaSessionPreferencesInitListener). - Design-system primitives under
views/ui/:TemplateBrand,BrandMark,PageHeader,MetricTile,FeatureCard,EmptyState,FilterBar,LocaleSwitcher,ThemeSwitcher. - Lumo badge readability fixes
(
[theme~="badge"][theme~="contrast"|"success"|"error"]) for the dark and jSentinel themes — the upstream Lumo light-mode colours were unreadable on the new backgrounds. - jSentinel-theme text colour overrides (
--lumo-header-text-color, explicit h1–h6 + form-control colours) so headings and form labels are not rendered black on a dark brand background.
- Custom
AppI18NProviderregistered via thei18n.providerinit-param inWEB-INF/web.xml— Vaadin V25 ignoresMETA-INF/servicesforI18NProvider, so the SPI mechanism the predecessor used was a silent no-op. ResourceBundle.Control.getNoFallbackControl(FORMAT_PROPERTIES)defeats the JVM-default-localeResourceBundlefallback trap: a missing translation forLocale.ENGLISHno longer cascades to the JVM default (German on the dev machine), it falls back to the base bundle.I18nstatic facade +I18nSupportmixin: every translation call carries an inline fallback string, so missing keys render the fallback rather than the raw key.- Translation bundles under
src/main/resources/vaadin-i18n/:translations.properties(EN ground truth) andtranslations_de.properties(~180 keys each). - Runtime locale switching:
LocaleSwitchersets the locale via a?lang=URL parameter andSessionPreferencesInitListenerapplies it before any view renders — survives full reload.
- Maven Wrapper regenerated to Maven 4.0.0-rc-5 (Apache wrapper
3.3.4,
only-scriptvariant). The old Takarimaven-wrapper.jarMavenWrapperDownloader.javaare gone.
- Java target JDK 26 (
maven.compiler.release=26); Vaadin 25.1.1, Jetty 12.1.8. _mutation-gateMaven profile runs PIT mutation coverage and thetools/pit-gate.shper-package floor checker.tools/pit-baselines.txtcarries the calibrated floors (overall 35 %, security packages 68 %–100 %, view packages 22 %–35 %); recalibrated after the V00.74 bump and the persistent drift store landed.- Surefire
<systemPropertyVariables>redirects tests away from the repo-rooted./data/tree (app.storage.dir=target/test-data) and disables HIBP network egress (app.hibp.enabled=false). maven-compiler-pluginannotationProcessorPathskeep*-processorbefore*-annotations(path order matters on JDK 21+ — reversed = silent no-emit, noMETA-INF/servicesentries written)._shadejarprofile builds a standalone Jetty fat-jar (application.jar) via nano-vaadin-jetty 04.00.00.- Vaadin-Maven-plugin-generated frontend tooling
(
package.json,tsconfig.json,types.d.ts,vite.config.ts) checked into VCS per Vaadin's own recommendation;vite.generated.tsstays untracked (auto-regenerated). - Dropped redundant top-level
tools.jackson.core:jackson-core/jackson-databinddependencies — both come transitively viaflow-server. com.fasterxml.jackson.core:jackson-annotations:2.21retained with a load-bearing comment: Vaadin 25.1.1's transitivetools.jackson.core:jackson-databind:3.1.xloadscom.fasterxml.jackson.annotation.JsonSerializeAsin its static initializer as a migration bridge. Removing the dep crashesvaadin:prepare-frontendwithNoClassDefFoundError. Drop when a future Vaadin release ships a databind that no longer triggers the Jackson 2 fallback.
- 196 unit + Browserless tests across views, listeners, providers,
i18n, bootstrap and security services. Test classes live under
junit.com.svenruppert.*(the PIT test pattern). - New
PersistentJSentinelVersionStoreProviderTestexercises thecurrent / increment / resetdelegation and verifies two providers share the same Eclipse-Store-backed state.
- SpotBugs clean.
AppUserrecord copies therolesset viaSet.copyOfin the compact constructor;UserDirectoryProviderno longer needs anMS_EXPOSE_REPsuppression after the IODH refactor.
com.svenruppert:security-for-flow:00.50.00dependency.- Default
InMemoryJSentinelVersionStoreSPI binding (replaced byPersistentJSentinelVersionStoreProviderso role revocations survive JVM restarts). views/main/GreetService.java; the oldMainViewplaceholder replaced bySecurityFeaturesView+ the newMainLayout.- Old
META-INF/servicesentries forcom.svenruppert.vaadin.security.authorization.*. - Obsolete docker scripts,
deploy.shand superseded views from the pre-jSentinel layout.