You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Vollständige Auflistung aller Funktionen und Erweiterungspunkte
in jSentinel 00.70.00 (Stand 2026-05-31, V00.70.00
feature-complete — alle acht Phasen aus Konzept-V00.70.00.md sind
gemerged: Tenant/Resource-Modell, 11 Persistence-Store-SPIs, Contract-
Testkit + Eclipse-Store-Referenz-Impl, JSentinelVersion-Drift-
Detection inkl. automatischem Capture im LoginView, Policy-API +
jSentinel-processor, RoleHierarchy + Any/All-Permission-Annotationen,
Account-Lifecycle / API-Keys / RefreshTokens / Rate-Limit, Phase-8
Secured-Komponenten + SessionManagementView + OpenAPI-Metadaten).
Geordnet nach Reaktor-Modul und Funktionsbereich. Jeder Eintrag nennt
das Modul, den vollqualifizierten Java-Namen und — wo sinnvoll — die
SPI-Datei unter META-INF/services/.
Konventionen: ✅ = ausgeliefert, voll abgedeckt; ⚠️ = experimentell
(@ExperimentalJSentinelApi); ❌ = bewusst nicht im Scope (siehe
§ "Was nicht im Scope ist" am Ende).
Compile-Time-Annotation-Processor: erzeugt <Type>Secured-Subklassen für @Secured-annotierte konkrete Klassen. Wird als <annotationProcessorPath> eingebunden. Basiert auf com.svenruppert:proxybuilder:00.11.00 + proxybuilder-annotations:00.11.00.
jSentinel-persistence-testkit
jSentinel-persistence-testkit
⚠️ Contract-Test-Suites für jede Persistence-Store-SPI: @Test default-Methoden-Interfaces, die ein eigener Store-Adapter implementiert, um automatisch gegen den Library-Persistence-Kontrakt verifiziert zu werden. Persistence-Tech-agnostisch.
jSentinel-persistence-eclipsestore
jSentinel-persistence-eclipsestore
⚠️ Eclipse-Store (org.eclipse.store:storage-embedded:4.1.0) Referenz-Impl jeder Persistence-Store-SPI; besteht dieselbe 95+ Contract-Suite wie die In-Memory-Defaults. Drop-in für durable Persistence.
demo-rest-shared
demo-rest-shared
Transport-Konstanten + JSON-Helper für REST-Demos
demo-vaadin
demo-vaadin
Vollständige Vaadin-Demo mit lokaler User-Verwaltung
demo-rest
demo-rest
JDK-HttpServer + interaktive CLI
demo-vaadin-rest-client
demo-vaadin-rest-client
Vaadin-UI gegen demo-rest-Backend, plus Step-Up- / Resource-Policy-Demo-Views
demo-standalone
demo-standalone
CLI Library-Borrowing-Demo + Member-Directory-Demo — zeigt beide Method-Security-Pfade nebeneinander
2. SPI-Contracts (ServiceLoader-basiert)
Alle SPIs werden über META-INF/services/<FQN> registriert und über
com.svenruppert.jsentinel.authorization.api.JSentinelServiceResolver
aufgelöst (cached AtomicReference + lazy ServiceLoader-Resolution).
Authentifizierung & Autorisierung
SPI
Modul
Default
Zweck
AuthenticationService<T, U>
core
— (anwendungsdefiniert)
Credential-Validation + Subject-Loading
AuthorizationService<U>
core
— (anwendungsdefiniert)
Subject → Rollen + (optional) Permissions
PermissionAuthorizationService<U>⚠️
core
—
Optionale Permission-API mit HasPermissions
AccessEvaluator<A>
core
siehe § Evaluatoren
Annotation-basierte Vaadin-Access-Entscheidung
AuthorizationEvaluator<A>
core
siehe § Evaluatoren
Adapter-neutrale Authorization-Entscheidung
ActionAuthorizationService<U>
core
StaticActionAuthorizationService
Methoden-/Action-Level-Berechtigungen
SubjectStore
core
siehe § Subject-Stores
Storage für das aktuelle Subject
LoginListener<U>
vaadin
—
Vaadin-Login-Lifecycle-Hooks
Audit
SPI
Modul
Default
Zweck
JSentinelAuditService
core
DefaultCompositeAuditService
Audit-Service mit publish(AuditEvent) + query(AuditQuery)
AuditSink
core
RingBufferAuditSink + LoggingAuditSink
Write-only-Sink für Audit-Pipeline
Brute-Force & Sessions
SPI
Modul
Default
Zweck
LoginAttemptPolicy
core
InMemoryLoginAttemptPolicy
Login-Throttling + Lockout-Entscheidungen
SessionPolicy<U>
core
TimeoutSessionPolicy
Lifecycle-Hooks + Idle/Absolute-Timeout
Logout
SPI
Modul
Default
Zweck
LogoutService
core
NoopLogoutService / SubjectClearingLogoutService
Zentraler Logout-Treiber mit Fan-out
LogoutListener
core
— (Anwender-Erweiterung)
Post-logout Side-Effects (Token-Revoke etc.)
SubjectSessionRegistry
core
InMemorySubjectSessionRegistry
Multi-Session-Tracking pro Subject (für AllSessionsOfSubject-Scope)
Persistence-Stores (Phase 2 — alle 11 ⚠️@ExperimentalJSentinelApi)
Jeder Store hat ein InMemory*Store-Default in jSentinel-core und
eine Eclipse-Store-Referenz-Impl in jSentinel-persistence-eclipsestore,
beide verifiziert über jSentinel-persistence-testkit-Contract-Tests.
issue(subject) / rotate(refresh) / revoke(refresh) über RefreshTokenStore; chain-link via markReplaced mit Replay-Defense; emittiert TokenRotated auf erfolgreicher Rotation
Rate-Limiting (Phase 7c — ⚠️)
SPI / Klasse
Modul
Default
Zweck
RateLimitPolicy
core/ratelimiting
InMemoryRateLimitPolicy (Sliding-Window)
Per-Scope Rate-Limit (getrennt von LoginAttemptPolicy); tryAcquire(RateLimitKey) → RateLimitDecision(Allowed | Throttled)
Store-backed Services (Phase 4b — ⚠️)
Alle nutzen die Phase-2 Stores als Backing-Store, sind tenant-scoped
und schlucken Persistence-Fehler im Audit/Notification-Pfad, damit
sie die Security-Flow-Auswertung nie blockieren.
Service
Modul
Backing-Store
StoreBackedJSentinelAuditService
core/audit
AuditEventStore
StoreBackedLoginAttemptPolicy
core/bruteforce
LoginAttemptStore (flacher Lockout)
StoreBackedSubjectSessionRegistry
core/logout
SessionStore + optionaler JSentinelVersionStore (Phase-4c-Snapshot beim Register)
StoreBackedRoleAuthorizationService<U>
core/authorization/api/roles
RoleAssignmentStore (generic über Subject-Type)
StoreBackedRememberMeService
core/authentication
RememberMeTokenStore + PasswordHasher
StoreBackedBootstrapStateService
core/bootstrap
BootstrapStateStore (idempotentes markCompleted)
3. Annotations
Annotation
Modul
Evaluator
Zweck
@RequiresRole({"ROLE_…"})
core
RequiresRoleEvaluator
Subject muss mindestens eine der genannten Rollen haben (Role-Hierarchy-aware)
@RequiresPermission({"foo:bar"})
core
RequiresPermissionEvaluator
Subject muss alle genannten Permissions haben (AND)
@RequiresAllPermissions({"a", "b"})
core
RequiresAllPermissionsEvaluator
Explizite AND-Semantik (Klarheit über @RequiresPermission)
@RequiresAnyPermission({"a", "b"})
core
RequiresAnyPermissionEvaluator
OR-Semantik — mindestens eine Permission reicht
@RequiresPolicy("doc.owner-or-admin")⚠️
core
RequiresPolicyEvaluator
Benannte Policy aus PolicyRegistry, mit Step-Up-Support
@ProtectedBy(class.class)
core
ProtectedByEvaluator
Eigene Logik via AccessEvaluator-Klasse
@JSentinelAnnotation(MyEvaluator.class)
core
— (Meta-Annotation)
Bindet eine projekt-eigene Annotation an einen Evaluator
@Secured
core
— (Compile-Time-Trigger)
Markiert eine konkrete Klasse, damit jSentinel-processor einen <Type>Secured-Wrapper generiert (RetentionPolicy.SOURCE)
@ExperimentalJSentinelApi(reason)
core
—
Markiert API als experimentell
Projekt-eigene Annotationen (Beispiele aus den Demos): @VisibleFor
(demo-vaadin), @CustomCheck (jSentinel-vaadin Tests).
InMemoryRateLimitPolicy.tryAcquire bei Throttle (Phase 7c)
AuditQuery(types, subjectId, from, to, limit) mit Factories
all(), ofType(...), forSubject(...). AuditQuery.subjectIdOf
und LoggingAuditSink decken alle 27 Varianten ab.
7. Audit-Pipeline-Bausteine
Klasse
Modul
Rolle
JSentinelAuditService (Interface)
core
API: publish(AuditEvent) + query(AuditQuery)
AuditSink (Interface)
core
Write-only, single-method, never-throws
NoopJSentinelAuditService
core
Default-Fallback wenn keine SPI registriert
CompositeAuditService
core
RingBuffer + zusätzliche Sinks; query gegen den RingBuffer
Custom-Element-Slot via setCustomElements(Component) / clearCustomElements()
LUMO-Theme-Variants vorverdrahtet
notifyOnLogin() konsultiert SessionPolicy.onLogin und führt B3-Rotation auf Invalidate aus
captureJSentinelVersionSnapshot() (Phase 4c-Followup): wenn sowohl JSentinelVersionStore als auch SubjectIdResolver als SPI registriert sind, liest die View beim erfolgreichen Login die aktuelle JSentinelVersion und schreibt sie in den VaadinJSentinelVersionContext. Strict-no-op + exception-swallowing, blockiert den Login-Flow nie.
Drift-Filter; RestSubjectResolver.resolveJSentinelVersionContext als opt-in Default-Methode. Bei Drift: 401 + WWW-Authenticate: SessionStale (RFC 7235-Style) und Audit-Event.
Extrahiert die fünf framework-supplied @Requires…-Annotationen aus Handler-Klassen. Produziert eine JSON-freie HandlerJSentinelMetadata-Struktur, die Apps in ihren eigenen OpenAPI-Build mergen. Custom @JSentinelAnnotation-Annotationen werden bewusst nicht exportiert (App-spezifische Semantik).
Registriert den Processor für javac / Maven-Compiler.
JSentinelEnforcer (in jSentinel-core)
Zentrale Enforcement-API, geteilt mit SecuredProxy. Methoden: requirePermission, requireAllPermissions, requireAnyPermission, requireRole, requireAnyRole, requirePolicy; plus die Generic-enforce(Method, Class) für den Dynamic-Proxy-Pfad. Wirft AccessDeniedException on deny.
Konsumenten binden das Modul über <annotationProcessorPaths> in
maven-compiler-plugin ein — nie als reguläre Compile-Dependency, da
der Processor selbst zur Runtime nicht im Classpath stehen muss. Die
generierte <Type>Secured-Klasse hat keine Restanforderungen ans
Konsumenten-Projekt (@GeneratedByProxyBuilder wird im
writeDefinedClass-Override gestrippt, weil
RetentionPolicy.SOURCE).
Annotation-Mapping (Method-Level wins über Class-Level):
Annotation
Generierter Enforcer-Call
@RequiresPermission("a")
JSentinelEnforcer.requirePermission("a")
@RequiresPermission({"a","b"})
JSentinelEnforcer.requireAllPermissions("a","b")
@RequiresAllPermissions({"a","b"})
JSentinelEnforcer.requireAllPermissions("a","b")
@RequiresAnyPermission({"a","b"})
JSentinelEnforcer.requireAnyPermission("a","b")
@RequiresRole("ADMIN")
JSentinelEnforcer.requireRole("ADMIN")
@RequiresRole({"A","B"})
JSentinelEnforcer.requireAnyRole("A","B")
@RequiresPolicy("p")
JSentinelEnforcer.requirePolicy("p")
Diagnostics für @Secured auf final Klassen oder Method-Security-
Annotationen auf final/private/static-Methoden werden vom
proxybuilder-Base-Processor als Diagnostic.Kind.ERROR emittiert —
kein Code in jSentinel-processor selbst nötig.
11. Subject-Stores im Vergleich
Adapter
Implementation
Scope
Inheritance
Vaadin
VaadinSessionSubjectStore
Vaadin-Session-Attribute
Folgt der VaadinSession
REST
anwendungsdefiniert via RestSubjectResolver
Pro Request
—
Standalone
ThreadLocalSubjectStore
Per-Thread
Nicht inherited (by design)
12. First-Run-Bootstrap
Komponente
Zweck
BootstrapMode (enum)
TRANSIENT_CONSOLE / PERSISTENT_FILE / DISABLED
BootstrapConfigurationLoader
Lädt aus sysprop security.bootstrap.* > env > defaults
BootstrapStateService
bootstrapRequired() / hasAdministrator()
BootstrapTokenStore (SPI)
In-Memory oder File-backed (./data/bootstrap.token, POSIX 0600)
via TimeoutSessionPolicy.Config.rotateSessionAfterLogin=true
demo-rest (JDK HttpServer + CLI)
Endpoint
Methode
Auth
Zweck
/api/bootstrap/status
GET
open
Bootstrap-Status
/api/bootstrap/admin
POST
bootstrap-token
Initial-Admin anlegen
/api/login
POST
open
Token holen
/api/logout
POST
bearer-token
Token revoken
/api/me
GET
bearer-token
Aktuelles Subject
/api/operations
GET
bearer-token
Erlaubte Operationen für Subject
/api/documents
GET / POST / PUT / DELETE
bearer + @RequiresPermission
Dokument-CRUD
/api/admin/status
GET
admin:access
Admin-Status
/api/admin/users
GET / POST
admin:roles
User listen / anlegen
/api/admin/users/{username}
PUT / DELETE
admin:roles
Rolle setzen / User löschen
/api/audit
GET
audit:read
Audit-Events (Query-Params type, subject)
Plus CLI-Client (DemoClient.main) mit Login, Operation-Listing,
Document-Operations.
demo-vaadin-rest-client (Vaadin-UI gegen demo-rest)
Bootstrap über /setup schickt POST /api/bootstrap/admin an Backend
Login schickt POST /api/login, cached RemoteUser lokal
Role-Admin-UI gegen Backend (PUT /api/admin/users/{username})
Audit-View gegen Backend (GET /api/audit)
HttpDemoBackendClient als einzige HTTP-fähige Klasse
demo-standalone (CLI)
Zeigt beide Method-Security-Pfade nebeneinander:
Kommando
Permission/Role
Pfad
Service
list
book:list (MEMBER)
Runtime / Dynamic-Proxy
LibraryService (Interface)
borrow <title>
book:borrow (MEMBER)
Runtime / Dynamic-Proxy
LibraryService
return <title>
book:return (MEMBER)
Runtime / Dynamic-Proxy
LibraryService
add <title>
book:add (LIBRARIAN)
Runtime / Dynamic-Proxy
LibraryService
remove <title>
@RequiresRole("ADMIN")
Runtime / Dynamic-Proxy
LibraryService
members
member:list (MEMBER)
Compile-Time / MemberDirectorySecured
MemberDirectory (konkrete Klasse)
invite <name> <email>
member:add OR member:invite (LIBRARIAN)
Compile-Time
MemberDirectory
remove-member <name>
member:remove AND member:audit-log (ADMIN)
Compile-Time
MemberDirectory
reset-members
@RequiresRole("ADMIN")
Compile-Time
MemberDirectory
help / quit
—
—
UI
Seeded Users: admin/admin, librarian/librarian, alice/alice.
Bücher (LibraryService) werden via SecuredProxy.wrap(...) gesichert
(JDK Dynamic Proxy auf das Interface). Members (MemberDirectory)
werden via new MemberDirectorySecured() instanziiert — die Klasse
wird zur Compile-Zeit vom SecuredAnnotationProcessor generiert.
Beide Pfade landen im selben JSentinelEnforcer.
Mutation Coverage (Stand 2026-05-31, V00.70 Refresh)
PIT-Re-Runs für die V00.70-Stacks. Die Library-Module liegen alle
bei ≥ 79 %, drei davon ≥ 95 %. Die nicht voll erreichte
jSentinel-vaadin-Marke kommt überwiegend von VoidMethodCallMutator-
Mutationen auf Vaadin-Component-Settern in den Phase-8-UI-Klassen
(SessionManagementView, SecuredButton-Konstruktor-Setup etc.) —
das Entfernen eines setSizeFull() / addClassName(…) / add(…)-
Aufrufs hat keinen testbar-beobachtbaren Effekt im JUnit-Harness.
Das Mutations-Surface ohne UI-Konstruktion liegt deutlich höher.
Modul
Coverage
Kommentar
jSentinel-core
86 % (1191/1381)
Up from 79 % historisch / 82 % erste V00.70-Messung. LoggingAuditSinkAllVariantsTest, CompositeAuditServiceTest, DefaultCompositeAuditServiceTest ergänzt — Audit-Paket von 39 % auf solid.
jSentinel-vaadin
79 % (242/305)
UI-Konstruktion-Mutationen (VoidMethodCallMutator auf Vaadin-Settern in SessionManagementView etc.) dominieren die Lücke; Phase-4c session.vaadin-Paket bei 91 %, authorization.impl bei 91 %.
(kein PIT-Run; Contracts werden über Consumer verifiziert)
jSentinel-persistence-eclipsestore
(PIT-Re-Run nach Phase 4a noch offen)
demo-vaadin
70 %
(alte Messung, vor V00.70-Demo-Glue)
demo-rest
49 %
demo-vaadin-rest-client
10 %
demo-standalone
86 %
PIT-Property-Fix: Der historische Parent-POM-Typo
pitest-test-classes=junit.com.svenruppert.* ließ PIT 0 Tests
finden (sämtliche Mutationen "no coverage"). Bei V00.70 auf
com.svenruppert.* korrigiert, sonst zeigt der Re-Run irrführende
0 %-Werte.
Test-Totals (Stand 2026-05-30, nach Phase-8-Commit)
❌ Spring Security / Jakarta Security Replacement — bewusst minimalistisch.
❌ OAuth2 / OIDC / SAML / LDAP / Kerberos — kann als eigener Adapter
obendrauf gebaut werden, aber nicht im Kern.
❌ Cluster-Mode out-of-the-box — Default-Implementations sind
in-memory + single-node. Die SPIs sind aber so geschnitten, dass
Redis-/DB-/IAM-Backends als Drop-in laufen würden.
❌ Policy-Composing-DSL — Annotationen und Code sind die
Konfigurations-Schicht.
❌ security-javafx — geplant, wartet auf realen JavaFX-Bedarf.
jSentinel-standalone deckt funktional Swing / JavaFX / CLI ab.