fix: resolve SonarQube reliability bugs and null-contract violations#54
Merged
Conversation
Tier 1 — reliability (BLOCKER S2095 resource leaks): - Wrap JDBI Update in try-with-resources in JdbiBackupCodeRepository and JdbiRefreshTokenRepository so the statement is closed if execute() throws. - Convert the testkit concurrency-scenario ExecutorService usages to try-with-resources (JDK 21 AutoCloseable), dropping the manual finally. Tier 2 — JSpecify null-contract corrections (S2583/S2637): - @nullable on bindNullable(Object value) params (the method exists to bind nullable values), Transport.fromWire(String), and the adapter clientIp / attachedUserHandle helpers that already returned null. - @nullable on Spring @RequestBody params that the existing handlers already null-guard (Spring can inject a null body); service layer still validates blank input, so no behavioral regression on the unauthenticated endpoints. - @nullable on PkAuthJwtAuthenticationToken.token (+ getToken/getCredentials), which eraseCredentials() already nulls. - Drop dead body==null guards in the email/SMS senders whose params are @nonnull by SPI contract. Verified: ./gradlew check passes; JDBI + DynamoDB integration and testkit concurrency TCK tests green. Security-reviewed: no exploitable changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
wolpert
enabled auto-merge (rebase)
June 11, 2026 14:57
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
Addresses the SonarQube findings driving the failed quality gate, focusing on genuine correctness issues rather than gaming the metric. Two tiers:
Tier 1 — Reliability (the rating mover)
Four
S2095BLOCKER resource leaks. TheEnew-code reliability rating requires at least one BLOCKER reliability bug — these are it.JdbiBackupCodeRepository/JdbiRefreshTokenRepository: JDBIUpdatewas built andexecute()-d without being closed ifexecute()threw → wrapped in try-with-resources.testkitChallengeStoreScenarios/RefreshTokenScenarios:ExecutorServiceconverted to try-with-resources (JDK 21AutoCloseable), removing the manualfinally.Tier 2 — JSpecify null-contract corrections (
S2583/S2637)These were flagged because defensive null-handling met a
@NullMarked@NonNullcontract. Fixed by making the contract honest, not by deleting safety checks:@NullableonbindNullable(Object value)(its whole purpose is binding nullable values),Transport.fromWire(String)(javadoc documents null handling), and the adapterclientIp/attachedUserHandlehelpers that already returned null.@Nullableon Spring@RequestBodyparams the handlers already null-guard (Spring genuinely injects null for absent bodies).@NullableonPkAuthJwtAuthenticationToken.token(+getToken/getCredentials), whicheraseCredentials()already nulls.body == nullguards in the email/SMS senders whose params are@NonNullby SPI contract.Deliberately not changed
To keep every change high-quality, these Sonar findings are better resolved in the SonarQube UI than by editing code:
jti == nullguards in the access-token stores — intentional defense-in-depth in security-sensitive validation; keep and mark intentional.OtpPepperResolverS2119"reuse Random" — false positive; it's a one-shotSecureRandomat startup.S6218arrayequals/hashCodeandS8692test-clock — out of scope (lower-value tiers).Verification
./gradlew checkpasses — compile, Error Prone, JSpecify nullness across all modules, Spotless.concurrentTakeOnce/concurrentRotationTCK race scenarios that exercise the changedExecutorServicecleanup.@Nullable @RequestBodyrelaxesrequired=true) is non-exploitable — the empty-input path is already reachable via{}and the service layer rejects blank tokens/codes.🤖 Generated with Claude Code