Skip to content

Conversation

@equinoxmatt
Copy link
Contributor

@equinoxmatt equinoxmatt commented Dec 4, 2025

Summary by Sourcery

Introduce SDK support for security-related operations centered around JWT minting.

New Features:

  • Add JWT helper class that mints tokens using a specified security strategy and context.
  • Add Security facade on the client to access JWT functionality via a fluent API.
  • Expose securityJwtMint method on the Deskpro client and underlying call sender to request JWTs from the host app.

Enhancements:

  • Extend Deskpro client types with JWT-related result and interface definitions, including token payload and expiry metadata.

@sourcery-ai
Copy link

sourcery-ai bot commented Dec 4, 2025

Reviewer's Guide

Adds a security abstraction to the Deskpro SDK client, exposing JWT minting via a new Security API that delegates to parent window methods when available and falls back to safe no-op defaults.

Sequence diagram for JWT minting via DeskproClient security API

sequenceDiagram
  actor IntegrationApp
  participant DeskproClient
  participant Security
  participant JWT
  participant ParentWindow

  IntegrationApp->>DeskproClient: security()
  DeskproClient-->>IntegrationApp: Security

  IntegrationApp->>Security: jwt(strategyName)
  Security-->>IntegrationApp: JWT

  IntegrationApp->>JWT: mint(context)
  JWT->>DeskproClient: securityJwtMint(strategyName, context)

  alt parent _securityJwtMint available
    DeskproClient->>ParentWindow: _securityJwtMint(strategyName, context)
    ParentWindow-->>DeskproClient: JwtMintResult
  else no parent _securityJwtMint
    DeskproClient-->>DeskproClient: use default securityJwtMint implementation
  end

  DeskproClient-->>JWT: JwtMintResult
  JWT-->>IntegrationApp: JwtMintResult
Loading

Class diagram for new DeskproClient security and JWT abstractions

classDiagram
  class IDeskproClient {
    <<interface>>
    +securityJwtMint(strategyName: string, context: Context) JwtMintResult
    +security() ISecurity
  }

  class DeskproClient {
    +securityJwtMint(strategyName: string, context: Context) JwtMintResult
    +security() ISecurity
  }

  class CoreCallSender {
    <<interface>>
    +_securityJwtMint(strategyName: string, context: Context) JwtMintResult
  }

  class ISecurity {
    <<interface>>
    +jwt(strategyName: string) IJWT
  }

  class Security {
    -client IDeskproClient
    +Security(client: IDeskproClient)
    +jwt(strategyName: string) IJWT
  }

  class IJWT {
    <<interface>>
    +mint(context: Context) JwtMintResult
  }

  class JWT {
    -client IDeskproClient
    -strategyName string
    +JWT(client: IDeskproClient, strategyName: string)
    +mint(context: Context) JwtMintResult
  }

  class JwtMintResult {
    +token string
    +expiresAt string
  }

  DeskproClient ..|> IDeskproClient
  Security ..|> ISecurity
  JWT ..|> IJWT

  DeskproClient --> Security : creates
  Security --> JWT : creates

  DeskproClient ..> CoreCallSender : delegates _securityJwtMint
  DeskproClient --> JwtMintResult
Loading

File-Level Changes

Change Details Files
Introduce Security and JWT helper classes on the client, exposing JWT minting via a fluent API.
  • Add JWT class that wraps the client’s securityJwtMint method with a mint(context) helper
  • Add Security class that exposes jwt(strategyName) to construct JWT helpers
  • Expose security() on DeskproClient to access the new Security API
src/client/client.ts
src/client/types.ts
Wire DeskproClient to call a new parent _securityJwtMint method and define a default no-op implementation.
  • Extend CoreCallSender and ChildMethods with _securityJwtMint(strategyName, context)
  • Add securityJwtMint method to IDeskproClient and DeskproClient instance with default async no-op returning empty string token
  • During initialisation, override securityJwtMint to delegate to parent._securityJwtMint when present, preserving error propagation
src/client/client.ts
src/client/types.ts
Define shared JWT-related types used by the new security API.
  • Introduce JwtMintResult interface with token and expiresAt fields
  • Introduce IJWT interface with mint(options) returning JwtMintResult
  • Introduce ISecurity interface with jwt(strategyName) returning IJWT
src/client/types.ts

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

@equinoxmatt equinoxmatt force-pushed the feature/sc-208287/-hmrc-jwt-add-jwt-feature-to-apps-sdk-client branch from 5286116 to f3e0331 Compare December 8, 2025 14:39
@equinoxmatt equinoxmatt marked this pull request as ready for review December 8, 2025 14:39
Copy link

@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:

  • The default implementation of securityJwtMint in the DeskproClient constructor returns a string, which does not match the declared Promise<JwtMintResult> type; consider either returning a JwtMintResult stub or throwing an explicit error for unsupported environments.
  • The securityJwtMint wrapper inside registerParentMethods wraps the call in a try/catch that simply rethrows the error; you can remove the try/catch and directly return parent._securityJwtMint(strategyName, context) for simpler code.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The default implementation of `securityJwtMint` in the `DeskproClient` constructor returns a string, which does not match the declared `Promise<JwtMintResult>` type; consider either returning a `JwtMintResult` stub or throwing an explicit error for unsupported environments.
- The `securityJwtMint` wrapper inside `registerParentMethods` wraps the call in a `try/catch` that simply rethrows the error; you can remove the `try/catch` and directly return `parent._securityJwtMint(strategyName, context)` for simpler code.

## Individual Comments

### Comment 1
<location> `src/client/client.ts:251` </location>
<code_context>

     this.sendDeskproUIMessage = async () => { };

+    this.securityJwtMint = async () => "";
+
     if (this.options.runAfterPageLoad) {
</code_context>

<issue_to_address>
**issue (bug_risk):** Default `securityJwtMint` implementation returns a string, which is inconsistent with the declared `Promise<JwtMintResult>` type.

This implementation should return a `JwtMintResult`-shaped object rather than a string to match the `Promise<JwtMintResult>` signature and avoid type or runtime mismatches for callers expecting `{ token, expiresAt }`.
</issue_to_address>

### Comment 2
<location> `src/client/client.ts:438-439` </location>
<code_context>
          const result = await parent._securityJwtMint(strategyName, context);
          return result;

</code_context>

<issue_to_address>
**suggestion (code-quality):** Inline variable that is immediately returned ([`inline-immediately-returned-variable`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/TypeScript/Default-Rules/inline-immediately-returned-variable))

```suggestion
          return await parent._securityJwtMint(strategyName, context);

```

<br/><details><summary>Explanation</summary>Something that we often see in people's code is assigning to a result variable
and then immediately returning it.

Returning the result directly shortens the code and removes an unnecessary
variable, reducing the mental load of reading the function.

Where intermediate variables can be useful is if they then get used as a
parameter or a condition, and the name can act like a comment on what the
variable represents. In the case where you're returning it from a function, the
function name is there to tell you what the result is, so the variable name
is unnecessary.
</details>
</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.

Copy link
Contributor

@AshleyDawson AshleyDawson left a comment

Choose a reason for hiding this comment

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

One tiny thing

@equinoxmatt equinoxmatt force-pushed the feature/sc-208287/-hmrc-jwt-add-jwt-feature-to-apps-sdk-client branch from f3e0331 to e440dfc Compare December 8, 2025 18:30
@AshleyDawson AshleyDawson merged commit e1382f8 into main Dec 16, 2025
4 of 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.

3 participants