00.83.00
Release date: 2026-09-01 Previous release: 00.82.00 Maven coordinates (parent):
eu.jsentinel:jCustos-community-parent:00.83.00Full changelog: GitHub release v00.83.00
Two credibility gaps. Large parts of the public surface still carried
@ExperimentalJCustosApi after running unchanged for six releases — including
types whose own Javadoc promised promotion “in V00.76”. And
RestJCustosBootstrap.decisionMapper(...) accepted configuration that never
reached the enforcement path. What changes is what the project tells you it
will stand behind.
Stable-API promotion
Forty-three types and eleven methods lose the experimental marker. The procedure is the one 00.79 established — form stability, real test coverage, a litmus test through an actual integration, and at least three minor releases of soak — applied rather than reinvented. Community drops from 343 marked files to 299.
| Module | Promoted | Since |
|---|---|---|
jCustos-core — credential/propagation | 14 types | 00.74 |
jCustos-core — @PropagateToken | 1 | 00.74 |
jCustos-core — JCustosServiceResolver | 7 methods | 00.74/00.76 |
jCustos-propagation | PropagatingProxy | 00.74 |
jCustos-propagation-oidc | 6 types | 00.74 |
jCustos-jwt | HttpJwksClient, NimbusJwtValidator, NimbusJwtSigner | 00.76/00.77 |
jCustos-oauth2 | 5 types (code flow, token endpoint, refresh rotation, state store) | 00.77 |
jCustos-dx | Health, HealthFinding, HealthStatus, PropagationBootstrap | 00.74 |
jCustos-dx — JCustosRuntime | 4 methods (summary, toMap, toJson, healthCheck) | 00.74.10 |
jCustos-dx-rest | RestCorsConfiguration, RestOpenApiMetadata (+ builders) | 00.74 |
jCustos-dx-standalone | InteractiveLogin*, ThreadPropagation* (5) | 00.74 |
The promise that had a condition attached
The propagation types read “stable promotion staged for V00.76”, and the
package Javadoc named the condition: after at least one real demo adoption —
which had never happened. @PropagateToken appeared only inside the library
modules and their own tests. So the adoption came first:
demo-jcustos-vaadin-rest-client now calls its backend through a
@PropagateToken interface with no token parameter and no Authorization
literal at any call site. It forced no signature change, which is what made the
promotion defensible rather than merely overdue.
SemVer commitments
For every promoted type: interfaces grow only through default methods; records
and enums grow only additively; annotations grow only through elements with
default values; no signature, record component or enum constant is removed
without a major version. Re-marking a promoted type is a SemVer regression —
StableApiPromotionGuardTest fails when it happens, naming the type.
Kept experimental, and why
The marker means two different things. Still soaking or awaiting their own
audit: jCustos-events (135) + testkit (11), the jCustos-core remainder
(111), the 00.79.20 hardening group (mTLS, PAR, JAR, JWE), jCustos-dpop (9),
jCustos-identity-oidc (3) and CallbackStateBinding (@since 00.81.00). A
design position, not a soak status: the permission API stays marked because
role-based access is the recommended production path. The adapter-side
00.70/00.74 surfaces (jCustos-vaadin, -rest, -persistence-eclipsestore,
-standalone) are out of this release’s scope.
A configured REST decision mapper now reaches enforcement (JS-SEC-026)
RestJCustosBootstrap.decisionMapper(...) and .errorBodies(...) took
configuration and dropped it: both were recorded as diagnostics while
RestAuthorizationFilter hard-wired its own HttpStatusDecisionMapper.
.errorBodies(...) was in a worse state still — nothing consumed it.
The seam went into jCustos-rest (RestDecisionMapping, RestErrorBodies,
which the existing DX interfaces now extend); existing lambdas compile
unchanged. Two details worth naming:
- The filter resolves per request, not at construction — applications build their filter before bootstrapping, so a snapshot would have missed configuration published moments later. Explicit constructor argument wins, then the published mapper, then the conservative default.
- The session-expiry path joins the other two — it wrote status and body
directly, so a
problem+jsonstrategy would have rendered two of three denials and left expiry as plain text.
Nothing changes for an application that never calls .decisionMapper(...).
Also in this release
docs/dx/5-minute-setup-propagation.md— the missing page in that series.ExperimentalJCustosApi’s own Javadoc now explains both meanings of the marker; the README’s stable/experimental section andFEATURES.md’s legend follow.- Two Javadoc promises corrected rather than deleted.
Verification
Full reactor green: 6632 tests, up from 6610 in 00.82. Each behavioural
change was verified by removing it — the demo adoption (2 of 4 tests fail when
@PropagateToken is removed), the promotion guard (fails and names the type),
the decision-mapper wiring (3 of 5 tests fail when the context lookup is
reverted). The pre-existing filter, mapper and session-lifetime tests pass
unchanged, demonstrating backwards compatibility. No mocks.
Upgrade
Drop-in. No API was broken and no default changed. Two things to know:
- If you implemented
RestDecisionMapperorRestErrorBodyStrategy, they now extend the newjCustos-restinterfaces. Source-compatible; recompile. - If you called
.decisionMapper(...)or.errorBodies(...)and worked around them having no effect, remove the workaround — the configuration now applies, and applying it twice may double-render a body.