Skip to content

Conversation

ancheetah
Copy link
Collaborator

@ancheetah ancheetah commented Jul 31, 2025

JIRA Ticket

https://pingidentity.atlassian.net/browse/SDKS-4202

Description

  • fixes unecessary re-renders in @pingidentity/protect-app
  • Updates Signals SDK to v5.6.0
  • Improves protect native e2e test
  • Updates Protect config
  • Updates Protect module readme with DaVinci quickstart
  • Changes namespace to @forgerock
  • Implements internal try-catch in protect module for improved error handling

Changeset added

Copy link

changeset-bot bot commented Jul 31, 2025

🦋 Changeset detected

Latest commit: 4f19711

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 10 packages
Name Type
@forgerock/protect Minor
@forgerock/davinci-client Minor
@forgerock/oidc-client Minor
@forgerock/sdk-types Minor
@forgerock/sdk-utilities Minor
@forgerock/iframe-manager Minor
@forgerock/sdk-logger Minor
@forgerock/sdk-oidc Minor
@forgerock/sdk-request-middleware Minor
@forgerock/storage Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

nx-cloud bot commented Jul 31, 2025

View your CI Pipeline Execution ↗ for commit 18677d9

Command Status Duration Result
nx run-many -t build ✅ Succeeded <1s View ↗
nx affected -t build typecheck lint test e2e-ci ✅ Succeeded 2m 36s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 3s View ↗

☁️ Nx Cloud last updated this comment at 2025-08-11 22:52:09 UTC

Copy link
Contributor

github-actions bot commented Jul 31, 2025

Deployed 3b5d297 to https://ForgeRock.github.io/ping-javascript-sdk/pr-362/3b5d29766977dd2f4d90486bce21b405efa97858 branch gh-pages in ForgeRock/ping-javascript-sdk

Copy link
Contributor

github-actions bot commented Jul 31, 2025

📦 Bundle Size Analysis

📦 Bundle Size Analysis

🆕 New Packages

🆕 @forgerock/protect - 152.3 KB (new)

➖ No Changes

@forgerock/oidc-client - 17.9 KB
@forgerock/davinci-client - 34.1 KB
@forgerock/sdk-utilities - 4.0 KB
@forgerock/device-client - 9.2 KB
@forgerock/sdk-types - 5.9 KB
@forgerock/iframe-manager - 2.4 KB
@forgerock/sdk-request-middleware - 4.2 KB
@forgerock/storage - 1.4 KB
@forgerock/sdk-logger - 1.6 KB
@forgerock/sdk-oidc - 3.5 KB


11 packages analyzed • Baseline from latest main build

Legend

🆕 New package
🔺 Size increased
🔻 Size decreased
➖ No change

ℹ️ How bundle sizes are calculated
  • Current Size: Total gzipped size of all files in the package's dist directory
  • Baseline: Comparison against the latest build from the main branch
  • Files included: All build outputs except source maps and TypeScript build cache
  • Exclusions: .map, .tsbuildinfo, and .d.ts.map files

🔄 Updated automatically on each push to this PR

@ancheetah ancheetah force-pushed the SDKS-4202-update-protect branch from 3163ccd to a7e22ea Compare August 5, 2025 14:55
@ancheetah ancheetah marked this pull request as ready for review August 5, 2025 15:02
@ancheetah
Copy link
Collaborator Author

Pending verification of agentTrust configuration option but can add later

@ancheetah ancheetah requested review from cerebrl and ryanbas21 August 5, 2025 15:03
Copy link
Collaborator

@ryanbas21 ryanbas21 left a comment

Choose a reason for hiding this comment

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

@ancheetah Can we just get a confirmation that we do not intend to release the signals SDK here?

This would be considered a major change i'd think.

Copy link
Collaborator

@cerebrl cerebrl left a comment

Choose a reason for hiding this comment

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

Just a few questions and suggestions.

# PingOne Protect

The Ping Protect module is intended to be used along with the ForgeRock JavaScript SDK to provide the Ping Protect feature.
The PingOne Protect module provides an API for interacting with the PingOne Signals (Protect) SDK to perform risk evaluations. It can be used with either a PingOne AIC/PingAM authentication journey with Protect callbacks or with a PingOne DaVinci flow with Protect connectors.
Copy link
Collaborator

Choose a reason for hiding this comment

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

To keep things symmetric, I'd use Nodes and Connectors, or use Callbacks and Collectors. In the above sentence your using terms from different categories.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good point. I'll change this to callbacks and collectors here. I do use the term connectors in the DaVinci section but I think it is more clear there the relationship between collectors and connectors.

Alternatively, you can delay the initialization until you receive the instruction from the server by way of the `ProtectCollector`. To do this, you would call the `start` method when the collector is present in the flow. The Protect collector is returned from the server when it is configured with either a PingOne Forms connector or HTTP connector with Custom HTML Template.

Comment on lines 17 to 28
```js
// PingOneProtectInitializeCallback methods
callback.getConfig();
callback.setClientError();
```

```js
// PingOneProtectEvaluationCallback methods
callback.setData();
callback.setClientError();
callback.getPauseBehavioralData();
```
Copy link
Collaborator

Choose a reason for hiding this comment

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

This may be a bit confusing for readers. This example block of APIs are really about this module but about the callback methods from the legacy SDK. We should probably preface this with a bit of explanation and also distinguish it from DaVinci Collectors.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What about removing this from the Full API section and moving it into a section at the bottom of the AIC quickstart with the title Protect Callback Methods. It would have some description like Relevant callback methods for PingOneProtectInitializeCallback and PingOneProtectEvaluationCallback.

We could even just remove these lines altogether since they're already covered in the quickstart.

Copy link
Collaborator

Choose a reason for hiding this comment

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

If we already cover it in a different section, let's go with your second statement.

```

The `@pingidentity/protect` module has a `protect()` function that accepts configuration options and returns a set of methods for interacting with Protect. The two main responsibilities of the Ping Protect module are the initialization of the profiling and data collection and the completion and preparation of the collected data for the server. You can find these two methods on the API returned by `protect()`.
The `@pingidentity/protect` module has a `protect()` function that accepts configuration options and returns a set of methods for interacting with Protect. The two main responsibilities of the PingOne Protect module are the initialization of the profiling and data collection and the completion and preparation of the collected data for the server. You can find these two methods on the API returned by `protect()`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

What was the reason for converting Ping to PingOne? I also noticed the one above. PingOne specifically refers to the multi-tenant, server product, of which this module doesn't directly relate to it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

My bad, didn't know this. I can change it back everywhere. I updated it to PingOne because that is how I saw Protect being referred to everywhere in the docs. But I suppose the module isn't necessarily the same thing.
https://docs.pingidentity.com/sdks/latest/sdks/integrations/integrate-with-pingone-protect.html
https://docs.pingidentity.com/connectors/p1_protect_connector.html

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, in the context of building a DaVinci flow, the Protect feature is configured and comes from the PingOne server and implemented wit that connector. But, from an SDK standpoint, PingOne itself is never directly used, and all interaction is with DaVinci.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Changed it back to just 'Ping' everywhere where it should be. Let me know if I missed one.

let data;

if (step.getCallbacksOfType('PingOneProtectEvaluationCallback')) {
try {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd like to prevent the wrapping of these methods with a try-catch. I wonder if we should at least have an internal try-catch to prevent this burden on the user.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We could add an internal try-catch to each method in our module to ensure they only return an error object instead of throwing. This does simplify the error handling section as well since we would be able to remove the try catches there too.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this would be good as it would help align this module more with our other modules where "throwing errors" is completely avoided.

// Asynchronous call
data = await protectAPI.getData();
data = await protectApi.getData();
if (typeof data !== 'string' && 'error' in data) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

The convention I have in my head for recommended patterns is something like this (which you're very close to):

const result = api.method();
if ('error' in result) {
  // handle error and return early
}
// handle success

My intent is for all errors to have an error property, so this can be relied on across all of our modules. If this is present, they have an error, if not, they have a success.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We can do this for most of the methods except for getData because the return type is a string instead of void. If you remove the typeof data !== 'string' check then you'll get a typescript error:

Type 'string | { error: unknown; }' is not assignable to type 'object'.
  Type 'string' is not assignable to type 'object'.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm, yeah, makes sense. I wonder if it's worth it to have a discussion around functions that return a primitive but also return errors. That would prevent the need to handle two different kinds of data types.


When calling `protect()`, you have many different options to configure what and how the data is collected. The most important and required of these settings is the `envId`. All other settings are optional.

The `start` method can be called at application startup, or when you receive the `ProtectCollector` from the server. We recommend you call `start` as soon as you can to collect as much data as possible for higher accuracy.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd like to emphasize this a bit more than this paragraph. Can we use headers for the different approaches and place "(recommended)" in the header text for startup time approach?

@ancheetah ancheetah force-pushed the SDKS-4202-update-protect branch 4 times, most recently from 474b08a to f1b1830 Compare August 8, 2025 15:30
@codecov-commenter
Copy link

codecov-commenter commented Aug 8, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 57.58%. Comparing base (e393843) to head (18677d9).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #362   +/-   ##
=======================================
  Coverage   57.58%   57.58%           
=======================================
  Files          32       32           
  Lines        2044     2044           
  Branches      320      320           
=======================================
  Hits         1177     1177           
  Misses        867      867           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ancheetah ancheetah requested a review from cerebrl August 8, 2025 15:36
@ancheetah ancheetah force-pushed the SDKS-4202-update-protect branch from f1b1830 to 4f19711 Compare August 8, 2025 16:48
@ancheetah ancheetah force-pushed the SDKS-4202-update-protect branch from 4f19711 to 18677d9 Compare August 11, 2025 22:48
@ancheetah ancheetah merged commit 19e72ce into main Aug 12, 2025
4 checks passed
@ancheetah ancheetah deleted the SDKS-4202-update-protect branch August 12, 2025 13:44
@ryanbas21 ryanbas21 mentioned this pull request Aug 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants