## 4.2.1 (2026-07-17)

### Documentation

- **nestjs-auth:** document missing IKeycloakTestingModuleOptions export ([0181e60](https://github.com/PhillipAWells/workspace/commit/0181e60))

### 🧱 Updated Dependencies

- Updated @pawells/typescript-common to 3.1.1
- Updated @pawells/metrics to 1.1.1
- Updated @pawells/logger to 4.2.1

## 4.2.0 (2026-07-17)

### Features

- add package sources for @pawells monorepo consolidation ([d5290a9](https://github.com/PhillipAWells/workspace/commit/d5290a9))

### Bug Fixes

- **nestjs-auth:** align graphql peer dependency to ^16.14.0 ([bdd29e3](https://github.com/PhillipAWells/workspace/commit/bdd29e3))
- **nestjs-auth:** add JSDoc, improve type safety, reorganize tests ([ad97871](https://github.com/PhillipAWells/workspace/commit/ad97871))
- correct TypeScript project references for consolidated workspace ([5e46113](https://github.com/PhillipAWells/workspace/commit/5e46113))

### Documentation

- **nestjs-auth:** enhance CLAUDE.md, README and package.json, add JSDoc to testing utilities and mocks ([10238e4](https://github.com/PhillipAWells/workspace/commit/10238e4))
- **workspace:** add per-package CLAUDE.md files ([8a32184](https://github.com/PhillipAWells/workspace/commit/8a32184))

### 🧱 Updated Dependencies

- Updated @pawells/typescript-common to 3.1.0
- Updated @pawells/metrics to 1.1.0
- Updated @pawells/logger to 4.2.0

# Changelog

All notable changes to this package will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [4.1.0] - 2026-07-14

### Added

- Token validation observability metrics via `@pawells/metrics`:
  - `pawells_auth_token_validation_duration_seconds` — histogram recording validation latency (labeled by mode: online|offline, result: valid|invalid) with standard 11-bucket distribution (5ms to 10s)
  - `pawells_auth_introspection_cache_total` — counter recording cache performance during online validation (labeled by result: hit|miss|negative_hit)
  - Both descriptors are registered idempotently on service construction; metrics are recorded in try-catch blocks and never break validation logic. Registering a `@pawells/metrics` exporter (e.g. via `@pawells/nestjs-metrics`) is required to actually collect these — without one, recording is a safe no-op.
- AND-logic authorization decorators: `@RequireAllRoles(...roles)` and `@RequireAllPermissions(...permissions)` for enforcing that a user must have ALL specified roles or permissions (in contrast to the OR-only semantics of `@Roles()` and `@Permissions()`)
- Metadata keys `REQUIRE_ALL_ROLES_KEY` and `REQUIRE_ALL_PERMISSIONS_KEY` for AND-logic authorization checks
- `RoleGuard` and `PermissionGuard` now check for both OR-logic and AND-logic metadata independently, allowing fine-grained authorization control
- `@KeycloakClaims()` parameter decorator to extract raw Keycloak token claims (`IKeycloakTokenClaims`) from the request, providing access to decoded JWT payload with all standard OIDC and Keycloak-specific claims
- `@GraphQLKeycloakClaims()` GraphQL-specific variant for injecting token claims into resolvers
- `clockToleranceSec` configuration option (optional, offline mode) — clock tolerance in seconds passed to jose's `jwtVerify` option, allowing tokens technically expired but within the tolerance window to be accepted. Solves NTP clock drift issues between Keycloak and resource server deployments.
- Optional negative caching for failed Keycloak token introspection results via `failedIntrospectionCacheTtlMs` config option (issue #63) — when configured, caches failed validations (invalid/expired/revoked tokens) for a short TTL to reduce redundant calls to Keycloak; disabled by default; separate from and never interferes with successful token caching.
- `mapUserFn` configuration hook (optional) for custom user identity transformation (issue #71) — allows reshaping the extracted `IKeycloakUser` object after successful token validation to support non-standard Keycloak protocol mappers (custom claims, multi-tenant claim namespacing, etc). The hook receives raw claims and the default-extracted user object, returns the transformed user. Only invoked on successful validation; exceptions propagate as errors rather than being swallowed.

### Changed

- Upgraded `@pawells/logger` to `^4.1.0`
- The internal introspection retry helper (`WithRetry`) now logs the underlying error on each retry attempt via the service's logger instead of discarding it silently, improving diagnosability of intermittent Keycloak introspection failures.

### Fixed

- `RoleGuard` and `PermissionGuard` now respect the `@Public()` decorator (issue #103). Previously, routes marked as public could still be rejected by these guards if they also carried role/permission metadata. Both guards now check for `IS_PUBLIC_KEY` at the start of `canActivate()`, bypassing all authorization checks for public routes, matching the behavior of `JwtAuthGuard`.
- `KeycloakTestingModule.forRootAsync()` now accepts async factory options (useFactory + inject) consistent with `KeycloakModule.forRootAsync()`, resolving #109. Previously, forRootAsync() was a duplicate of forRoot() and did not support deferred configuration; now it properly defers module initialization using `CreateAsyncProviders()` helper and accepts `IKeycloakTestingModuleAsyncOptions`.
- Offline JWT validation now applies the same claims-shape guard used by the online path, rejecting signature-valid-but-malformed tokens (missing `sub`/`iss`/`aud`) with an `invalid_claims` error instead of producing a user object with `id: undefined`.
- `KeycloakTestingModule.forRoot()` and `forRootAsync()` now register the dynamic module with `global: true`, matching the production `KeycloakModule`'s DI registration (previously test consumers needed to import the testing module into every feature module manually).
- Documentation: corrected misleading JSDoc on the `clockSkewSeconds` config field, which implied it affects offline JWT expiry validation. It is accepted and schema-validated but not currently read by the validation service — use `clockToleranceSec` instead.

## [4.0.4] - 2026-07-11

### Fixed

- Documentation corrections: added missing `@example` JSDoc blocks to `MockKeycloakTokenValidationService`'s `SetValidateTokenResult()`, `SetExtractUserResult()`, and `Reset()` methods.

## [4.0.3]

### Added

- `KeycloakModule` — NestJS module for Keycloak token validation (online introspection or offline JWKS)
- `JwtAuthGuard`, `RoleGuard`, `PermissionGuard` — HTTP and GraphQL authorization guards for JWT authentication
- `@Public()`, `@Auth()`, `@Roles()`, `@Permissions()`, `@CurrentUser()`, `@AuthToken()` decorators for HTTP routes
- `@GraphQLCurrentUser()`, `@GraphQLAuthToken()`, `@GraphQLContextParam()`, `@GraphQLUser()` decorators for GraphQL resolvers
- `MockKeycloakTokenValidationService` — testing mock for stubbing token validation in unit tests
- `KeycloakAuthError` — typed error class for Keycloak-specific exceptions
- Configuration validation via `ValidateKeycloakConfig()` and Zod schema

[Unreleased]: https://github.com/PhillipAWells/workspace/compare/nestjs-auth@4.1.0...HEAD
[4.1.0]: https://github.com/PhillipAWells/workspace/compare/nestjs-auth@4.0.4...nestjs-auth@4.1.0
[4.0.4]: https://github.com/PhillipAWells/workspace/compare/nestjs-auth@4.0.3...nestjs-auth@4.0.4
[4.0.3]: https://github.com/PhillipAWells/workspace/releases/tag/nestjs-auth@4.0.3

