Skip to content

Add support for restricted data stores#30

Merged
orpiske merged 1 commit intowanaku-ai:mainfrom
orpiske:ci-issue-640-add-support-for-services-auth
Nov 20, 2025
Merged

Add support for restricted data stores#30
orpiske merged 1 commit intowanaku-ai:mainfrom
orpiske:ci-issue-640-add-support-for-services-auth

Conversation

@orpiske
Copy link
Copy Markdown
Contributor

@orpiske orpiske commented Nov 20, 2025

  • Also move the reusable security bits to a new module

Ref: wanaku-ai/wanaku#640

Summary by Sourcery

Centralize OAuth2 authentication logic into a new security module and refactor discovery and services clients to use common security abstractions

New Features:

  • Add capabilities-security module with ServiceAuthenticator, SecurityServiceConfig, ServiceAuthException, and TokenEndpoint for centralized OAuth2 handling

Enhancements:

  • Generalize DiscoveryAuthenticator to ServiceAuthenticator and unify service configuration into a single ServiceConfig interface with DefaultServiceConfig
  • Refactor DiscoveryServiceHttpClient and ServicesHttpClient to use the new ServiceAuthenticator and ServiceConfig abstractions

Build:

  • Introduce capabilities-security as a new Maven module and update POMs for capabilities-services-client, capabilities-discovery, and the BOM to include the security dependency

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Nov 20, 2025

Reviewer's Guide

This PR implements support for restricted data stores by extracting shared OAuth2 authentication components into a new security module and refactoring existing discovery and services clients to use generic ServiceAuthenticator and ServiceConfig interfaces.

Class diagram for refactored authentication and configuration classes

classDiagram
    class ServiceAuthenticator {
        - SecurityServiceConfig config
        - AccessToken accessToken
        - RefreshToken refreshToken
        - Instant creationTime
        + ServiceAuthenticator(SecurityServiceConfig config)
        - renewToken(SecurityServiceConfig config)
        - createTokenRequest(SecurityServiceConfig config)
        - getClientAuthentication(SecurityServiceConfig config)
        - requestToken(TokenRequest request)
        + toHeaderValue()
    }
    class SecurityServiceConfig {
        <<interface>>
        + getClientId() String
        + getSecret() String
        + getTokenEndpoint() String
    }
    class ServiceConfig {
        <<interface>>
        + getBaseUrl() String
        + getSerializer() Serializer
        + getClientId() String
        + getSecret() String
        + getTokenEndpoint() String
    }
    class DefaultServiceConfig {
        + baseUrl String
        + serializer Serializer
        + clientId String
        + secret String
        + tokenEndpoint String
        + DefaultServiceConfig(Builder builder)
        + getBaseUrl() String
        + getSerializer() Serializer
        + getClientId() String
        + getSecret() String
        + getTokenEndpoint() String
        + Builder
    }
    class ServiceAuthException {
        + ServiceAuthException()
        + ServiceAuthException(String message)
        + ServiceAuthException(String message, Throwable cause)
        + ServiceAuthException(Throwable cause)
        + ServiceAuthException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)
    }
    ServiceAuthenticator --> SecurityServiceConfig
    ServiceConfig --|> SecurityServiceConfig
    DefaultServiceConfig --|> ServiceConfig
    ServiceAuthenticator ..> ServiceAuthException
Loading

Class diagram for updated HTTP client classes

classDiagram
    class DiscoveryServiceHttpClient {
        - String serviceBasePath
        - ServiceAuthenticator serviceAuthenticator
        - String baseUrl
        - Serializer serializer
        - HttpClient httpClient
        + DiscoveryServiceHttpClient(ServiceConfig config)
        - sanitize(ServiceConfig config) String
        + executePost(...)
        + ping(String id)
        + updateState(String id, ServiceState serviceState)
    }
    class ServicesHttpClient {
        - String baseUrl
        - Serializer serializer
        - ObjectMapper objectMapper
        - ServiceAuthenticator serviceAuthenticator
        - HttpClient httpClient
        + ServicesHttpClient(ServiceConfig config)
        - sanitize(ServiceConfig config) String
        + executePost(...)
        + executePut(...)
        + executeGet(...)
        + executeDelete(...)
    }
    DiscoveryServiceHttpClient --> ServiceAuthenticator
    ServicesHttpClient --> ServiceAuthenticator
    DiscoveryServiceHttpClient --> ServiceConfig
    ServicesHttpClient --> ServiceConfig
Loading

Class diagram for removed and replaced classes

classDiagram
    class DiscoveryAuthenticator {
        - DiscoveryServiceConfig config
        - AccessToken accessToken
        - RefreshToken refreshToken
        - Instant creationTime
        + DiscoveryAuthenticator(DiscoveryServiceConfig config)
        - renewToken(DiscoveryServiceConfig config)
        - createTokenRequest(DiscoveryServiceConfig config)
        - getClientAuthentication(DiscoveryServiceConfig config)
        - requestToken(TokenRequest request)
    }
    class DiscoveryServiceConfig {
        <<interface>>
        + getBaseUrl() String
        + getSerializer() Serializer
        + getClientId() String
        + getSecret() String
        + getTokenEndpoint() String
    }
    class DefaultDiscoveryServiceConfig {
        + baseUrl String
        + serializer Serializer
        + clientId String
        + secret String
        + tokenEndpoint String
        + DefaultDiscoveryServiceConfig(Builder builder)
        + getBaseUrl() String
        + getSerializer() Serializer
        + getClientId() String
        + getSecret() String
        + getTokenEndpoint() String
        + Builder
    }
    class ServicesClientConfig {
        <<interface>>
        + getBaseUrl() String
        + getSerializer() Serializer
        + getClientId() String
        + getSecret() String
        + getTokenEndpoint() String
    }
    class DefaultServicesClientConfig {
        + baseUrl String
        + serializer Serializer
        + clientId String
        + secret String
        + tokenEndpoint String
        + DefaultServicesClientConfig(Builder builder)
        + getBaseUrl() String
        + getSerializer() Serializer
        + getClientId() String
        + getSecret() String
        + getTokenEndpoint() String
        + Builder
    }
    class DiscoveryAuthException {
        + DiscoveryAuthException()
        + DiscoveryAuthException(String message)
        + DiscoveryAuthException(String message, Throwable cause)
        + DiscoveryAuthException(Throwable cause)
        + DiscoveryAuthException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)
    }
Loading

File-Level Changes

Change Details Files
Extracted and centralized OAuth2 authentication logic into a new security module
  • Added capabilities-security module with ServiceAuthenticator, TokenEndpoint, and ServiceAuthException
  • Introduced SecurityServiceConfig interface for client ID, secret, and token endpoint
capabilities-security/pom.xml
capabilities-security/src/main/java/ai/wanaku/capabilities/sdk/security/ServiceAuthenticator.java
capabilities-security/src/main/java/ai/wanaku/capabilities/sdk/security/TokenEndpoint.java
capabilities-security/src/main/java/ai/wanaku/capabilities/sdk/security/exceptions/ServiceAuthException.java
capabilities-common/src/main/java/ai/wanaku/capabilities/sdk/common/security/SecurityServiceConfig.java
Renamed discovery-specific config and authenticator to generic service counterparts
  • Renamed DiscoveryAuthenticator to ServiceAuthenticator and DiscoveryServiceConfig to SecurityServiceConfig/ServiceConfig
  • Refactored DefaultDiscoveryServiceConfig into DefaultServiceConfig in common config
capabilities-discovery/src/main/java/ai/wanaku/capabilities/sdk/discovery/DiscoveryAuthenticator.java
capabilities-discovery/src/main/java/ai/wanaku/capabilities/sdk/discovery/config/DefaultDiscoveryServiceConfig.java
capabilities-common/src/main/java/ai/wanaku/capabilities/sdk/common/config/DefaultServiceConfig.java
Updated HTTP clients to authenticate via the new generic ServiceAuthenticator
  • Replaced DiscoveryAuthenticator and ServicesClientConfig references with ServiceAuthenticator and ServiceConfig
  • Added authorization header wiring in both DiscoveryServiceHttpClient and ServicesHttpClient
capabilities-discovery/src/main/java/ai/wanaku/capabilities/sdk/discovery/DiscoveryServiceHttpClient.java
capabilities-services-client/src/main/java/ai/wanaku/capabilities/sdk/services/ServicesHttpClient.java
capabilities-services-client/src/main/java/ai/wanaku/capabilities/sdk/services/config/ServiceConfig.java
Updated project dependencies and POMs to integrate the new security module
  • Added capabilities-security as a dependency in services-client, discovery, and BOM modules
  • Included capabilities-security in the root multi-module build
pom.xml
capabilities-services-client/pom.xml
capabilities-discovery/pom.xml
capabilities-bom/pom.xml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • There’s duplicated sanitize(baseUrl) logic in both HTTP clients—consider extracting it into a shared helper to reduce code repetition.
  • Since you’ve renamed DiscoveryServiceConfig/DiscoveryAuthenticator to ServiceConfig/ServiceAuthenticator, add deprecation aliases or a brief migration note so existing clients won’t break immediately.
  • You’re building HTTP requests with auth headers in multiple places—think about centralizing request construction or auth injection to make future extensions easier.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- There’s duplicated sanitize(baseUrl) logic in both HTTP clients—consider extracting it into a shared helper to reduce code repetition.
- Since you’ve renamed DiscoveryServiceConfig/DiscoveryAuthenticator to ServiceConfig/ServiceAuthenticator, add deprecation aliases or a brief migration note so existing clients won’t break immediately.
- You’re building HTTP requests with auth headers in multiple places—think about centralizing request construction or auth injection to make future extensions easier.

## Individual Comments

### Comment 1
<location> `capabilities-discovery/src/main/java/ai/wanaku/capabilities/sdk/discovery/DiscoveryAuthenticator.java:113` </location>
<code_context>
             TokenErrorResponse errorResponse = response.toErrorResponse();
-            LOG.error("Unable to authenticate with discovery service: {}", errorResponse.getErrorObject().getDescription());
+            LOG.error("Unable to authenticate with service: {}", errorResponse.getErrorObject().getDescription());
             throw new RuntimeException(errorResponse.getErrorObject().getDescription());
         }

</code_context>

<issue_to_address>
**suggestion:** Throwing RuntimeException on authentication error may obscure error handling.

Use a specific exception like ServiceAuthException for authentication failures to improve error handling consistency.

Suggested implementation:

```java
            LOG.error("Unable to authenticate with service: {}", errorResponse.getErrorObject().getDescription());
            throw new ServiceAuthException(errorResponse.getErrorObject().getDescription());

```

```java
import com.nimbusds.oauth2.sdk.AccessTokenResponse;
import com.nimbusds.oauth2.sdk.AuthorizationGrant;
import com.nimbusds.oauth2.sdk.ClientCredentialsGrant;
import org.slf4j.LoggerFactory;
import ai.wanaku.capabilities.sdk.discovery.ServiceAuthException;

```

If `ServiceAuthException` does not already exist, you need to create it. For example, add this file:

`capabilities-discovery/src/main/java/ai/wanaku/capabilities/sdk/discovery/ServiceAuthException.java`:

```java
package ai.wanaku.capabilities.sdk.discovery;

public class ServiceAuthException extends RuntimeException {
    public ServiceAuthException(String message) {
        super(message);
    }
    public ServiceAuthException(String message, Throwable cause) {
        super(message, cause);
    }
}
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

- Also move the reusable security bits to a new module

Ref: wanaku-ai/wanaku#640
@orpiske orpiske force-pushed the ci-issue-640-add-support-for-services-auth branch from 776c99a to d33a2a7 Compare November 20, 2025 21:54
@orpiske orpiske merged commit 1e34d07 into wanaku-ai:main Nov 20, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant