From 90a42ed0537e0e379cc8d623cece3d7722d2778a Mon Sep 17 00:00:00 2001 From: Ned Wolpert Date: Sat, 13 Jun 2026 08:31:13 -0700 Subject: [PATCH] chore(release): prepare 2.0.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Versions: gradle.properties 1.3.1-SNAPSHOT -> 2.0.0-SNAPSHOT; browser SDK package.json 1.3.1 -> 2.0.0. - CHANGELOG: add the [2.0.0] entry (Added / Changed / Fixed / Security). - @since: bump the 14 files added after the v1.3.1 tag from @since 1.3.1 to @since 2.0.0 (v1.3.1 was cut 2026-06-06, before that API landed, so those tags were wrong — verified zero @since 1.3.1 existed at the tag). - Docs/site: sweep current-version references (CLAUDE.md, README, stability, SECURITY, RELEASE, site/index.html, site/og-image.svg) to 2.0.0; historical "shipped in 1.x" notes and the [1.3.1] changelog history are preserved. The major-version bump is driven by one breaking embedded-API change (the start* ceremonies now return sealed StartRegistrationResult / StartAuthenticationResult and CeremonyRateLimitedException was removed). The HTTP /auth/** wire contract is unchanged. Note: site/og-image.png (a pre-rendered social card) still shows v1.3.1 and must be regenerated from the updated og-image.svg. Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 84 +++++++++++++++++++ CLAUDE.md | 2 +- README.md | 2 +- RELEASE.md | 2 +- SECURITY.md | 2 +- clients/passkeys-browser/package.json | 2 +- docs/stability.md | 6 +- gradle.properties | 2 +- .../pkauth/admin/DefaultAdminService.java | 4 +- .../pkauth/api/StartAuthenticationResult.java | 8 +- .../pkauth/api/StartRegistrationResult.java | 8 +- .../pkauth/config/CeremonyConfig.java | 2 +- .../pkauth/config/RelyingPartyConfig.java | 2 +- .../pkauth/spi/PkAuthPersistenceResponse.java | 4 +- .../codeheadsystems/pkauth/jwt/JwtConfig.java | 2 +- .../pkauth/jwt/TokenTtlPolicy.java | 2 +- .../pkauth/refresh/RefreshTokenConfig.java | 2 +- .../pkauth/refresh/RefreshTtlPolicy.java | 2 +- .../pkauth/refresh/spi/Amr.java | 6 +- .../spring/config/PkAuthProperties.java | 2 +- .../BackupCodeRepositoryScenarios.java | 4 +- .../testkit/OtpRepositoryScenarios.java | 4 +- site/index.html | 20 ++--- site/og-image.svg | 2 +- 24 files changed, 130 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f485e5..0269981 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,90 @@ The 0.x line is treated as a single pre-stable development series — see 1.0.0 stabilisation cut; for 0.x history consult `git log` against the relevant tags. +## [2.0.0] — 2026-06-13 + +The first 2.x release. The bulk of the work is correctness, hardening, and +maintainability; the major-version bump is driven by **one breaking change to +the embedded Java API** — the `start*` ceremony methods (described under +Changed). The HTTP `/auth/**` wire contract (request/response bodies and status +codes) is unchanged, so deployments that integrate through the Spring / +Dropwizard / Micronaut adapters and the JSON API need no code changes. + +### Changed + +- **Breaking (embedded API only): `start*` ceremonies now return sealed result + sums.** `PasskeyAuthenticationService.startRegistration` / + `startAuthentication` return `StartRegistrationResult` / + `StartAuthenticationResult` (`Started | RateLimited`) instead of the bare + response envelope, mirroring the `finish*` ceremonies, and the + `CeremonyRateLimitedException` type is removed. A rate-limit refusal is now a + value every adapter pattern-matches (compile-checked exhaustiveness) rather + than an exception thrown across the boundary. Hosts using the Spring / + Dropwizard / Micronaut adapters are unaffected; only code calling + `PasskeyAuthenticationService` directly must switch on the result. The + `200` / `429` wire responses are identical to before. +- **Host→domain config translation is centralized.** `RelyingPartyConfig.from(…)` + and `CeremonyConfig.from(…)` carry the shared validation and conservative + default-coalescing (UV `REQUIRED`, counter-regression `REJECT`) the three + adapter factories previously duplicated; an unset knob can only resolve to the + secure default. +- **The persistence-failure response envelope is centralized** in + `PkAuthPersistenceResponse` (HTTP `503`, body + `{"error":"persistence_failure","operation":…}`), so all three adapters emit a + byte-identical body and a backend outage cannot leak a framework-default 500. +- **Build / CI.** SonarQube Cloud was dropped for the JVM modules in favour of + native JaCoCo line + branch coverage gates (ADR 0018); it is retained for the + TypeScript browser SDK. CI now fails if `PKAUTH_SKIP_TESTCONTAINERS=1` leaks + into the gate, adds a `workflow_dispatch` trigger for on-demand runs, and skips + the secret-dependent SonarQube / Stryker steps on Dependabot PRs. + +### Added + +- **Passkey-only hosts can boot without the alt-flow SPIs** (backup-codes / OTP / + magic-link), in the admin API and Spring starter. +- **Config range validation** on the OTP, backup-code, and magic-link `Config` + records — non-positive TTLs, attempt caps, and rate limits are rejected at + construction instead of producing never-verifiable or instantly-expired codes. +- **Concurrent consume-once acceptance scenarios** for OTP and backup codes in + the testkit (`OtpRepositoryScenarios`, `BackupCodeRepositoryScenarios`), run + against real Postgres and DynamoDB Local — the atomic single-use guarantee is + now proven for those flows, not just refresh tokens. + +### Fixed + +- **DynamoDB refresh-token rotation no longer scorches a token family on a + transient error.** A `TransactionCanceledException` is treated as a + replay/race (revoking the family) only when the parent's freshness condition + actually failed (`ConditionalCheckFailed`); throughput / transaction-conflict / + validation cancellations are rethrown as a retryable 5xx, and an + indeterminable reason fails closed. +- **Ceremony user-verification now defaults to `REQUIRED`,** and the UV / + resident-key / attestation / counter-regression knobs are surfaced through the + Spring properties. +- **DynamoDB maintenance scans** (`deleteExpiredBefore`) are constrained with a + server-side `begins_with(pk, …)` filter instead of reading the whole shared + single table. +- **OTP no-active-OTP branch** drops a misleading constant-time self-compare; the + throwaway HMAC that equalizes response timing is kept. +- **Admin phone-verification** maps the `SendResult` sum with an exhaustive + switch instead of an unchecked downcast. +- Hardened CBOR / converter robustness and added end-to-end forged / replayed + ceremony coverage. + +### Security + +- **esbuild forced to ≥ 0.28.1** to clear GHSA-gv7w-rqvm-qjhr (HIGH). It is a + build-time, dev-only transitive dependency of the browser SDK (never shipped in + the published bundle), and the advisory targets esbuild's Deno module, so the + practical exposure was low — but the bump clears the advisory at the source. +- **Browser SDK base64url** no longer uses a ReDoS-shaped regex (SonarQube + S5852 / CWE-1333); `encode` / `decode` use `replaceAll` with string literals, + byte-identical output. +- **Documentation corrections to security-relevant behaviour.** OTP codes are + hashed with HMAC-SHA256 + a server-side pepper (not Argon2id); the + `userVerification = REQUIRED` default and the ≥ 16-byte OTP pepper requirement + are now documented in the threat model and operator guide. + ## [1.3.1] — 2026-06-06 Patch release: a browser-SDK build fix, a Micronaut admin toggle, and diff --git a/CLAUDE.md b/CLAUDE.md index 0d56b6d..9e2d478 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## What this is -pk-auth is a **passkeys-first authentication library set for the JVM**, published to Maven Central under `com.codeheadsystems`. All modules share one version (`gradle.properties` → currently `1.3.1-SNAPSHOT`). It is *not* an identity provider: it owns passkeys/credentials, never users — the host maps users via the `UserLookup` SPI. +pk-auth is a **passkeys-first authentication library set for the JVM**, published to Maven Central under `com.codeheadsystems`. All modules share one version (`gradle.properties` → currently `2.0.0-SNAPSHOT`). It is *not* an identity provider: it owns passkeys/credentials, never users — the host maps users via the `UserLookup` SPI. The canonical architecture reference is [`DESIGN.md`](./DESIGN.md); per-decision rationale lives in [`docs/adr/`](./docs/adr/) (Nygard format, numbered). Read the relevant ADR before changing cross-module behavior. diff --git a/README.md b/README.md index 3807430..ff19d3f 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,7 @@ tests and Playwright end-to-end suites: ## Status 1.0.0 cut the stable baseline; the current development line is -**1.3.1-SNAPSHOT** (see `gradle.properties` for the authoritative +**2.0.0-SNAPSHOT** (see `gradle.properties` for the authoritative version). The 1.1 line added per-audience JWT TTLs, the `AccessTokenStore` (stateful access tokens), the `UserDeletionService` fan-out, and the `pk-auth-refresh-tokens` diff --git a/RELEASE.md b/RELEASE.md index 6c6bd9c..d73fdff 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -194,7 +194,7 @@ git tag, because the release is already tagged (`vX.Y.Z`) for Maven Central. Pin the SDK version to that same number so the two stay in lockstep. > The committed `version` in `package.json` is the in-development line -> (e.g. `1.3.0-SNAPSHOT`), mirroring `gradle.properties`. `SNAPSHOT` is a valid +> (e.g. `2.0.0-SNAPSHOT`), mirroring `gradle.properties`. `SNAPSHOT` is a valid > semver prerelease identifier, so it will not be published by accident — step 1 > always pins it to the concrete release version first. After publishing, you may > leave `package.json` at the published version or restore the `-SNAPSHOT` line on diff --git a/SECURITY.md b/SECURITY.md index 989c382..bca0f46 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -36,7 +36,7 @@ Use one of these private channels instead: Please include, as far as you can: -- The affected module(s) and version (e.g. `pk-auth-core 1.3.0`). +- The affected module(s) and version (e.g. `pk-auth-core 2.0.0`). - A description of the issue and its impact (what an attacker can do). - Steps to reproduce — a minimal proof of concept, failing test, or request sequence is ideal. diff --git a/clients/passkeys-browser/package.json b/clients/passkeys-browser/package.json index b7ec3ee..b548fe7 100644 --- a/clients/passkeys-browser/package.json +++ b/clients/passkeys-browser/package.json @@ -1,6 +1,6 @@ { "name": "@pk-auth/passkeys-browser", - "version": "1.3.1", + "version": "2.0.0", "description": "pk-auth browser SDK: WebAuthn ceremonies + admin operations against the pk-auth wire contract.", "license": "MIT", "author": "Ned Wolpert", diff --git a/docs/stability.md b/docs/stability.md index d2532d3..c049b4a 100644 --- a/docs/stability.md +++ b/docs/stability.md @@ -1,13 +1,13 @@ # pk-auth Stability and Versioning -## Current status: 1.x +## Current status: 2.x pk-auth is **post-1.0** as of the `v1.0.0` tag. The current development line is -**1.3.1-SNAPSHOT** (`gradle.properties` is authoritative); the 1.1, 1.2, and +**2.0.0-SNAPSHOT** (`gradle.properties` is authoritative); the 1.1, 1.2, and 1.3 releases have shipped. See [`CHANGELOG.md`](../CHANGELOG.md) for the per-release delta. -The 1.x line follows [Semantic Versioning](https://semver.org/): +Post-1.0, pk-auth follows [Semantic Versioning](https://semver.org/): | Change type | Version bump | |---|---| diff --git a/gradle.properties b/gradle.properties index 0777b2d..654f753 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,4 +21,4 @@ org.gradle.jvmargs=-Xmx2g \ # Project identity group=com.codeheadsystems -version=1.3.1-SNAPSHOT +version=2.0.0-SNAPSHOT diff --git a/pk-auth-admin-api/src/main/java/com/codeheadsystems/pkauth/admin/DefaultAdminService.java b/pk-auth-admin-api/src/main/java/com/codeheadsystems/pkauth/admin/DefaultAdminService.java index 52b1c9c..cf99c2b 100644 --- a/pk-auth-admin-api/src/main/java/com/codeheadsystems/pkauth/admin/DefaultAdminService.java +++ b/pk-auth-admin-api/src/main/java/com/codeheadsystems/pkauth/admin/DefaultAdminService.java @@ -279,7 +279,7 @@ private static AdminResult notConfigured(String feature) { * Config)} overload) to construct a service. Using a record keeps construction sites concise and * self-documenting through Java's named component syntax. * - * @since 1.3.1 + * @since 2.0.0 */ public record Dependencies( CredentialRepository credentialRepository, @@ -297,7 +297,7 @@ public record Dependencies( * Convenience for a passkey-only deployment: credentials and user lookup only, with every * alt-flow service absent. * - * @since 1.3.1 + * @since 2.0.0 */ public static Dependencies passkeyOnly( CredentialRepository credentialRepository, UserLookup userLookup) { diff --git a/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/api/StartAuthenticationResult.java b/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/api/StartAuthenticationResult.java index 47584b7..949cef7 100644 --- a/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/api/StartAuthenticationResult.java +++ b/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/api/StartAuthenticationResult.java @@ -15,7 +15,7 @@ * any challenge was created; adapters map it to HTTP {@code 429}. * * - * @since 1.3.1 + * @since 2.0.0 */ public sealed interface StartAuthenticationResult permits StartAuthenticationResult.Started, StartAuthenticationResult.RateLimited { @@ -24,7 +24,7 @@ public sealed interface StartAuthenticationResult * The limiter allowed the ceremony; {@code response} carries the WebAuthn request options. * * @param response the start-authentication envelope. - * @since 1.3.1 + * @since 2.0.0 */ record Started(StartAuthenticationResponse response) implements StartAuthenticationResult { public Started { @@ -36,7 +36,7 @@ record Started(StartAuthenticationResponse response) implements StartAuthenticat * The configured rate limiter refused the call before any challenge was created. * * @param bucket which limiter bucket denied the call ({@code "ip"} or {@code "username"}). - * @since 1.3.1 + * @since 2.0.0 */ record RateLimited(String bucket) implements StartAuthenticationResult { public RateLimited { @@ -52,7 +52,7 @@ record RateLimited(String bucket) implements StartAuthenticationResult { * * @return the start-authentication envelope. * @throws IllegalStateException if this result is {@link RateLimited}. - * @since 1.3.1 + * @since 2.0.0 */ default StartAuthenticationResponse responseOrThrow() { if (this instanceof Started started) { diff --git a/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/api/StartRegistrationResult.java b/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/api/StartRegistrationResult.java index b36a3f8..e7a4060 100644 --- a/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/api/StartRegistrationResult.java +++ b/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/api/StartRegistrationResult.java @@ -15,7 +15,7 @@ * any challenge was created; adapters map it to HTTP {@code 429}. * * - * @since 1.3.1 + * @since 2.0.0 */ public sealed interface StartRegistrationResult permits StartRegistrationResult.Started, StartRegistrationResult.RateLimited { @@ -24,7 +24,7 @@ public sealed interface StartRegistrationResult * The limiter allowed the ceremony; {@code response} carries the WebAuthn creation options. * * @param response the start-registration envelope. - * @since 1.3.1 + * @since 2.0.0 */ record Started(StartRegistrationResponse response) implements StartRegistrationResult { public Started { @@ -36,7 +36,7 @@ record Started(StartRegistrationResponse response) implements StartRegistrationR * The configured rate limiter refused the call before any challenge was created. * * @param bucket which limiter bucket denied the call ({@code "ip"} or {@code "username"}). - * @since 1.3.1 + * @since 2.0.0 */ record RateLimited(String bucket) implements StartRegistrationResult { public RateLimited { @@ -52,7 +52,7 @@ record RateLimited(String bucket) implements StartRegistrationResult { * * @return the start-registration envelope. * @throws IllegalStateException if this result is {@link RateLimited}. - * @since 1.3.1 + * @since 2.0.0 */ default StartRegistrationResponse responseOrThrow() { if (this instanceof Started started) { diff --git a/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/config/CeremonyConfig.java b/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/config/CeremonyConfig.java index 9cd8231..1ac7fc2 100644 --- a/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/config/CeremonyConfig.java +++ b/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/config/CeremonyConfig.java @@ -63,7 +63,7 @@ public static CeremonyConfig defaults() { * @param attestationConveyance attestation conveyance, or null for the default. * @param counterRegression counter-regression policy, or null for the default. * @return the resolved ceremony config. - * @since 1.3.1 + * @since 2.0.0 */ public static CeremonyConfig from( @Nullable Duration challengeTtl, diff --git a/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/config/RelyingPartyConfig.java b/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/config/RelyingPartyConfig.java index 4f1f767..13c136b 100644 --- a/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/config/RelyingPartyConfig.java +++ b/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/config/RelyingPartyConfig.java @@ -42,7 +42,7 @@ public record RelyingPartyConfig(String id, String name, Set origins) { * @param name human-readable RP name, or null/blank if unset. * @param origins acceptable client-reported origins, or null/empty if unset; copied defensively. * @return the validated relying-party config. - * @since 1.3.1 + * @since 2.0.0 */ public static RelyingPartyConfig from( @Nullable String id, @Nullable String name, @Nullable Collection origins) { diff --git a/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/spi/PkAuthPersistenceResponse.java b/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/spi/PkAuthPersistenceResponse.java index e24e0e7..6b9026d 100644 --- a/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/spi/PkAuthPersistenceResponse.java +++ b/pk-auth-core/src/main/java/com/codeheadsystems/pkauth/spi/PkAuthPersistenceResponse.java @@ -14,7 +14,7 @@ * every adapter, instead of one accidentally leaking a framework-default 500 with a stack trace. * Each adapter keeps only its framework-specific glue (response type, logging). * - * @since 1.3.1 + * @since 2.0.0 */ public final class PkAuthPersistenceResponse { @@ -32,7 +32,7 @@ private PkAuthPersistenceResponse() {} * * @param exception the persistence failure to render. * @return an insertion-ordered map with {@code error} and {@code operation} keys. - * @since 1.3.1 + * @since 2.0.0 */ public static Map body(PkAuthPersistenceException exception) { Map body = new LinkedHashMap<>(); diff --git a/pk-auth-jwt/src/main/java/com/codeheadsystems/pkauth/jwt/JwtConfig.java b/pk-auth-jwt/src/main/java/com/codeheadsystems/pkauth/jwt/JwtConfig.java index 896e2be..3afd577 100644 --- a/pk-auth-jwt/src/main/java/com/codeheadsystems/pkauth/jwt/JwtConfig.java +++ b/pk-auth-jwt/src/main/java/com/codeheadsystems/pkauth/jwt/JwtConfig.java @@ -112,7 +112,7 @@ public static JwtConfig defaults(String issuer, String audience) { * @param defaultTtl the access-token TTL, or {@code null} for {@link #DEFAULT_TOKEN_TTL}. * @param ttlsByAudience per-audience TTL overrides, or {@code null}/empty for a uniform TTL. * @return the assembled config. - * @since 1.3.1 + * @since 2.0.0 */ public static JwtConfig from( String issuer, diff --git a/pk-auth-jwt/src/main/java/com/codeheadsystems/pkauth/jwt/TokenTtlPolicy.java b/pk-auth-jwt/src/main/java/com/codeheadsystems/pkauth/jwt/TokenTtlPolicy.java index e452875..2376493 100644 --- a/pk-auth-jwt/src/main/java/com/codeheadsystems/pkauth/jwt/TokenTtlPolicy.java +++ b/pk-auth-jwt/src/main/java/com/codeheadsystems/pkauth/jwt/TokenTtlPolicy.java @@ -94,7 +94,7 @@ public String toString() { * @param defaultTtl the fallback TTL for any audience not in {@code overrides}. * @param overrides per-audience TTL overrides, or {@code null}/empty for a uniform TTL. * @return the resolved policy. - * @since 1.3.1 + * @since 2.0.0 */ static TokenTtlPolicy from(Duration defaultTtl, @Nullable Map overrides) { return overrides == null || overrides.isEmpty() diff --git a/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/RefreshTokenConfig.java b/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/RefreshTokenConfig.java index 14c1039..554f5de 100644 --- a/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/RefreshTokenConfig.java +++ b/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/RefreshTokenConfig.java @@ -74,7 +74,7 @@ public static RefreshTokenConfig defaults() { * @param cleanupRetention forensic retention window, or {@code null} for {@link * #DEFAULT_CLEANUP_RETENTION}. * @return the assembled config. - * @since 1.3.1 + * @since 2.0.0 */ public static RefreshTokenConfig from( @Nullable Duration defaultTtl, diff --git a/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/RefreshTtlPolicy.java b/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/RefreshTtlPolicy.java index 1cfd2c4..94a9254 100644 --- a/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/RefreshTtlPolicy.java +++ b/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/RefreshTtlPolicy.java @@ -48,7 +48,7 @@ default Set knownAudiences() { * @param defaultTtl the fallback TTL for any audience not in {@code overrides}. * @param overrides per-audience TTL overrides, or {@code null}/empty for a uniform TTL. * @return the resolved policy. - * @since 1.3.1 + * @since 2.0.0 */ static RefreshTtlPolicy from(Duration defaultTtl, @Nullable Map overrides) { return overrides == null || overrides.isEmpty() diff --git a/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/spi/Amr.java b/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/spi/Amr.java index 8985e2b..7787a5a 100644 --- a/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/spi/Amr.java +++ b/pk-auth-refresh-tokens/src/main/java/com/codeheadsystems/pkauth/refresh/spi/Amr.java @@ -13,7 +13,7 @@ *

The comma separator is safe because {@code RefreshTokenRecord} rejects any {@code amr} entry * containing a {@code ','} at construction time, so a round-trip is lossless. * - * @since 1.3.1 + * @since 2.0.0 */ public final class Amr { @@ -27,7 +27,7 @@ private Amr() {} * * @param amr the non-empty, comma-free references from a {@code RefreshTokenRecord}. * @return the comma-joined storage form. - * @since 1.3.1 + * @since 2.0.0 */ public static String encode(List amr) { return String.join(",", amr); @@ -40,7 +40,7 @@ public static String encode(List amr) { * * @param stored the stored comma-separated value, possibly {@code null} or blank. * @return the decoded references, never empty. - * @since 1.3.1 + * @since 2.0.0 */ public static List decode(@Nullable String stored) { if (stored == null || stored.isBlank()) { diff --git a/pk-auth-spring-boot-starter/src/main/java/com/codeheadsystems/pkauth/spring/config/PkAuthProperties.java b/pk-auth-spring-boot-starter/src/main/java/com/codeheadsystems/pkauth/spring/config/PkAuthProperties.java index d2b70f5..7dd871d 100644 --- a/pk-auth-spring-boot-starter/src/main/java/com/codeheadsystems/pkauth/spring/config/PkAuthProperties.java +++ b/pk-auth-spring-boot-starter/src/main/java/com/codeheadsystems/pkauth/spring/config/PkAuthProperties.java @@ -102,7 +102,7 @@ public record Jwt( * @param residentKey discoverable-credential requirement (default {@code PREFERRED}) * @param attestation attestation conveyance preference (default {@code NONE}) * @param counterRegression signature-counter regression policy (default {@code REJECT}) - * @since 1.3.1 + * @since 2.0.0 */ public record Ceremony( @Nullable Duration challengeTtl, diff --git a/pk-auth-testkit/src/main/java/com/codeheadsystems/pkauth/testkit/BackupCodeRepositoryScenarios.java b/pk-auth-testkit/src/main/java/com/codeheadsystems/pkauth/testkit/BackupCodeRepositoryScenarios.java index ed3b606..251e464 100644 --- a/pk-auth-testkit/src/main/java/com/codeheadsystems/pkauth/testkit/BackupCodeRepositoryScenarios.java +++ b/pk-auth-testkit/src/main/java/com/codeheadsystems/pkauth/testkit/BackupCodeRepositoryScenarios.java @@ -23,7 +23,7 @@ * once — cannot regress in one implementation while passing in another. Mirrors {@link * RefreshTokenScenarios}'s concurrent rotation race for the refresh-token path. * - * @since 1.3.1 + * @since 2.0.0 */ public final class BackupCodeRepositoryScenarios { @@ -41,7 +41,7 @@ public BackupCodeRepositoryScenarios(BackupCodeRepository repository) { * code. * * @throws Exception if a worker thread is interrupted. - * @since 1.3.1 + * @since 2.0.0 */ public void concurrentConsumeYieldsExactlyOneWinner() throws Exception { UserHandle user = UserHandle.random(); diff --git a/pk-auth-testkit/src/main/java/com/codeheadsystems/pkauth/testkit/OtpRepositoryScenarios.java b/pk-auth-testkit/src/main/java/com/codeheadsystems/pkauth/testkit/OtpRepositoryScenarios.java index 4bcf696..123c506 100644 --- a/pk-auth-testkit/src/main/java/com/codeheadsystems/pkauth/testkit/OtpRepositoryScenarios.java +++ b/pk-auth-testkit/src/main/java/com/codeheadsystems/pkauth/testkit/OtpRepositoryScenarios.java @@ -23,7 +23,7 @@ * one implementation while passing in another. Mirrors {@link RefreshTokenScenarios}'s concurrent * rotation race for the refresh-token path. * - * @since 1.3.1 + * @since 2.0.0 */ public final class OtpRepositoryScenarios { @@ -43,7 +43,7 @@ public OtpRepositoryScenarios(OtpRepository repository) { * enabling OTP reuse. * * @throws Exception if a worker thread is interrupted. - * @since 1.3.1 + * @since 2.0.0 */ public void concurrentConsumeYieldsExactlyOneWinner() throws Exception { UserHandle user = UserHandle.random(); diff --git a/site/index.html b/site/index.html index 9d8441e..1e7de66 100644 --- a/site/index.html +++ b/site/index.html @@ -1098,7 +1098,7 @@

- v1.3.1 + v2.0.0 JDK 21 MIT WebAuthn4J @@ -1146,9 +1146,9 @@

// One adapter, one persistence module, done.
 dependencies {
-  implementation("com.codeheadsystems:pk-auth-spring-boot-starter:1.3.1")
-  implementation("com.codeheadsystems:pk-auth-persistence-jdbi:1.3.1")
-  implementation("com.codeheadsystems:pk-auth-admin-api:1.3.1")
+  implementation("com.codeheadsystems:pk-auth-spring-boot-starter:2.0.0")
+  implementation("com.codeheadsystems:pk-auth-persistence-jdbi:2.0.0")
+  implementation("com.codeheadsystems:pk-auth-admin-api:2.0.0")
 }
@@ -1332,9 +1332,9 @@

Add the adapter, persistence, and admin API.

dependencies {
-  implementation("com.codeheadsystems:pk-auth-spring-boot-starter:1.3.1")
-  implementation("com.codeheadsystems:pk-auth-persistence-jdbi:1.3.1")
-  implementation("com.codeheadsystems:pk-auth-admin-api:1.3.1")
+  implementation("com.codeheadsystems:pk-auth-spring-boot-starter:2.0.0")
+  implementation("com.codeheadsystems:pk-auth-persistence-jdbi:2.0.0")
+  implementation("com.codeheadsystems:pk-auth-admin-api:2.0.0")
 }
@@ -1343,7 +1343,7 @@

Add the adapter, persistence, and admin API.

<dependency>
   <groupId>com.codeheadsystems</groupId>
   <artifactId>pk-auth-spring-boot-starter</artifactId>
-  <version>1.3.1</version>
+  <version>2.0.0</version>
 </dependency>
 <!-- + pk-auth-persistence-jdbi, pk-auth-admin-api -->
@@ -1754,7 +1754,7 @@

pk-auth

A passkey credential layer for the JVM. MIT-licensed. Three adapters, one wire contract, your user table.

-

v1.3.1 · JDK 21 · WebAuthn4J

+

v2.0.0 · JDK 21 · WebAuthn4J