Skip to content

P1RECMOB-3476: Add recognize module and journey integration - #229

Open
mariodigirolamo1 wants to merge 10 commits into
ForgeRock:developfrom
mariodigirolamo1:develop
Open

P1RECMOB-3476: Add recognize module and journey integration#229
mariodigirolamo1 wants to merge 10 commits into
ForgeRock:developfrom
mariodigirolamo1:develop

Conversation

@mariodigirolamo1

@mariodigirolamo1 mariodigirolamo1 commented Jul 23, 2026

Copy link
Copy Markdown

JIRA Ticket

https://pingidentity.atlassian.net/browse/P1RECMOB-3476

Description

Summary

Introduces the recognize module — a proxy wrapper around the Keyless SDK (v6.0.0) that bridges PingAM Journey and PingOne DaVinci flows with biometric recognition (face enroll/authenticate).

What's in scope:

  • recognize/ module: core Recognize entry point, RecognizeException (with error code propagation), and RecognizeSuccess
  • Journey integration ✅: PingOneRecognizeEnrollCallback and PingOneRecognizeAuthenticateCallback — handles setup → enroll/auth lifecycle drivenby AbstractRecognizeCallback
  • DaVinci integration 🚧: RecognizeEnrollCollector and RecognizeAuthenticateCollector scaffolded and partially implemented — basic operation dispatch works but error handling is incomplete and there are no tests. This will be finalized in the next iteration.
  • Optional selfie retrieval on both enroll and auth paths
  • enroll from clientState support in the auth flow
  • Sample app wired to a Recognize Journey for manual testing
  • Unit tests covering Journey callbacks and the core wrapper

What's NOT in scope: DaVinci direct Keyless SDK calls (deferred, tracked in epic).

Review guidance

  • Start here: recognize/src/main/kotlin/com/pingidentity/recognize/ — core + DaVinci under davinci/, Journey under journey/
  • Journey path is the primary review surface — Recognize.kt, AbstractRecognizeCallback, and the two Journey callbacks are the correctness-critical code
  • DaVinci collectors are WIP — review them for structural direction only; error handling and tests are pending
  • Error handling: RecognizeException wraps KeylessSdkError codes — worth checking propagation is complete on the Journey path; DaVinci is known incomplete
  • The Journey callback test (RecognizeCallbackTest.kt, 1176 lines) is the most thorough coverage in this PR
  • CHANGELOG.md has the user-facing entry

⚠️ Build prerequisite — Cloudsmith tokens

The Keyless SDK is fetched from two private Cloudsmith Maven repos. settings.gradle.kts reads the tokens as Gradle properties:

cloudsmithTokenRecognize → https://dl.cloudsmith.io//keyless/partners/maven/
cloudsmithTokenAesWrap → https://dl.cloudsmith.io//keyless/aeswrap/maven/

For local builds — add to ~/.gradle/gradle.properties (not committed):
cloudsmithTokenRecognize=
cloudsmithTokenAesWrap=

For CI — both tokens must be injected as environment variables or Gradle properties in the pipeline config, otherwise dependency resolution will fail at the settings.gradle.kts phase (before any module is compiled).

Tokens should be obtainable from the Keyless/partners team or your internal secrets store.

Summary by CodeRabbit

  • New Features

    • Added PingOne Recognize biometric enrollment and authentication for Journey and DaVinci flows.
    • Added optional selfie retrieval, client-state handling, and structured error reporting.
    • Added automatic SDK initialization and callback/collector registration.
    • Added Recognize integration to the sample application.
  • Documentation

    • Added setup, configuration, error-handling, and troubleshooting guidance.
  • Tests

    • Added coverage for enrollment, authentication, configuration, errors, and registration.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new Android recognize module integrating PingOne Recognize through coroutine SDK wrappers, Journey callbacks, DaVinci collectors, AndroidX Startup registration, tests, documentation, and sample application wiring.

Changes

Recognize integration

Layer / File(s) Summary
SDK wrappers, exceptions, and module foundation
recognize/src/main/kotlin/com/pingidentity/recognize/Recognize.kt, recognize/src/main/kotlin/com/pingidentity/recognize/RecognizeSuccess.kt, recognize/src/main/kotlin/com/pingidentity/recognize/RecognizeException.kt, recognize/src/main/AndroidManifest.xml, recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeKeylessInitializer.kt, recognize/src/test/kotlin/com/pingidentity/recognize/*
Introduces suspendable Keyless operations, result type with selfie and client state, normalized exceptions with code and debugging info, Keyless SDK initialization, and wrapper tests.
Journey callback foundation and configuration
recognize/src/main/kotlin/com/pingidentity/recognize/journey/AbstractRecognizeCallback.kt, recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeCallback.kt, recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeConfig.kt, recognize/src/main/kotlin/com/pingidentity/recognize/journey/CallbackInitializer.kt
Adds callback base class with field parsing and config builders, factory callback for operation-type dispatch, configuration DSL with selfie control, and Startup registration.
Journey enrollment and authentication callbacks
recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeEnrollCallback.kt, recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt
Implements enrollment and authentication operations with client-state fallback, configurable selfie retrieval, exception normalization, and result submission.
Journey callback testing
recognize/src/test/kotlin/com/pingidentity/recognize/journey/*
Tests callback initialization, operation dispatch, field parsing, configurable selfie retrieval, enroll-from-clientState fallback, and fixed result field submission.
Sample app Journey integration
samples/pingsampleapp/src/main/java/.../JourneyContinueNode.kt
Wires Recognize callback dispatch into the sample app, triggers callback operations in Compose side effects, and suppresses default button progression.
DaVinci collector foundation and shared parsing
recognize/src/main/kotlin/com/pingidentity/recognize/davinci/AbstractRecognizeCollector.kt, recognize/src/main/kotlin/com/pingidentity/recognize/davinci/CollectorInitializer.kt, recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeCollector.kt
Introduces collector base class with operation-type dispatch, shared field initialization, and result payload management. Registers collectors with DaVinci Startup.
DaVinci enrollment and authentication collectors
recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeEnrollCollector.kt, recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeAuthenticateCollector.kt
Implements enrollment and authentication collectors with configuration construction, setup chaining, operation execution, error mapping, and JSON payload formatting.
DaVinci collector testing
recognize/src/test/kotlin/com/pingidentity/recognize/davinci/*
Tests collector initialization, operation dispatch, configuration parsing, success and failure payloads, error code mapping, and client state handling.
Build configuration, repositories, and documentation
recognize/build.gradle.kts, gradle/libs.versions.toml, settings.gradle.kts, recognize/README.md, samples/pingsampleapp/build.gradle.kts
Adds module build script with plugins and dependencies, configures Cloudsmith repositories, adds Keyless SDK catalog entry, includes comprehensive usage documentation for Journey and DaVinci flows, and wires sample app dependency.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Journey
  participant RecognizeCallback
  participant Recognize
  participant Keyless
  Journey->>RecognizeCallback: provide operationType and callback fields
  RecognizeCallback->>Recognize: configure and invoke enroll or authenticate
  Recognize->>Keyless: execute callback-based SDK operation
  Keyless->>Recognize: return success or failure
  Recognize->>Journey: submit result fields
Loading
sequenceDiagram
  participant DaVinci
  participant RecognizeCollector
  participant Recognize
  participant Keyless
  DaVinci->>RecognizeCollector: provide operationType and collector input
  RecognizeCollector->>Recognize: setup and execute selected operation
  Recognize->>Keyless: invoke enrollment or authentication
  Keyless->>Recognize: return operation result
  Recognize->>DaVinci: return flat JSON payload
Loading

Suggested reviewers: spetrov, vibhorgoswami, witrisna

Poem

I'm a rabbit with a Recognize carrot,
Enroll and auth now hop through each parrot.
Journey paths bloom, DaVinci flows sing,
SDK callbacks do their springy thing.
With selfies and errors neatly in sight,
The module takes flight—boing, goodnight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the new recognize module and its Journey integration, which are central changes in the pull request.
Description check ✅ Passed The description includes the required JIRA Ticket and Description sections and provides detailed scope, testing, review, and build information.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mariodigirolamo1
mariodigirolamo1 marked this pull request as ready for review July 23, 2026 13:24

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (5)
recognize/src/test/kotlin/com/pingidentity/recognize/davinci/CollectorInitializerTest.kt (1)

25-33: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert the registered factory’s concrete collector.

assertNotNull would pass even if "RECOGNIZE" were mapped to the wrong factory. Verify that invoking the registered entry produces RecognizeCollector, using the CollectorFactory API for factory invocation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@recognize/src/test/kotlin/com/pingidentity/recognize/davinci/CollectorInitializerTest.kt`
around lines 25 - 33, Update the test create registers RECOGNIZE collector and
returns factory to invoke the registered "RECOGNIZE" entry through the
CollectorFactory API, then assert the produced collector is a
RecognizeCollector. Replace the insufficient assertNotNull check while
preserving the existing factory identity assertion.
recognize/src/test/kotlin/com/pingidentity/recognize/journey/RecognizeCallbackTest.kt (1)

84-104: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Extract a shared JSON-builder helper to reduce duplication.

Most tests in this file hand-roll a full multi-line JSON string just to vary a single field (mobileSDKOptions entry, operationType, etc.). The sibling RecognizeAuthenticateCollectorTest.kt already solves this with a small authInput(...) helper taking named defaults plus an optional mobileSDKOptions builder lambda — the same pattern here would cut this file's size considerably and make each test's actual variable clearer at a glance.

Also applies to: 217-242, 496-522, 527-551, 617-643, 655-681, 684-710, 713-739, 742-768, 771-797, 833-862

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@recognize/src/test/kotlin/com/pingidentity/recognize/journey/RecognizeCallbackTest.kt`
around lines 84 - 104, Extract a shared JSON-builder helper for the repeated
callback payloads in RecognizeCallbackTest, following the authInput pattern from
RecognizeAuthenticateCollectorTest. Give it named defaults for common fields and
an optional mobileSDKOptions builder, then update metadataCallbackJson and the
referenced test payload builders to use it while keeping each test’s variable
fields explicit.
recognize/src/main/kotlin/com/pingidentity/recognize/davinci/AbstractRecognizeCollector.kt (1)

28-28: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider internal visibility for this base class.

AbstractRecognizeCollector and its subclasses are only referenced within this module (via CollectorFactory.register in CollectorInitializer.kt), not part of a documented public API surface.

As per coding guidelines: "Prefer internal for module-private APIs, and declare public explicitly on the documented API surface."

♻️ Suggested visibility change
-abstract class AbstractRecognizeCollector : Collector<JsonObject> {
+internal abstract class AbstractRecognizeCollector : Collector<JsonObject> {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@recognize/src/main/kotlin/com/pingidentity/recognize/davinci/AbstractRecognizeCollector.kt`
at line 28, Change AbstractRecognizeCollector to internal visibility, and update
any directly declared subclasses if needed to satisfy Kotlin visibility rules.
Keep the CollectorFactory.register integration and documented public API
unchanged.

Source: Coding guidelines

recognize/src/main/kotlin/com/pingidentity/recognize/davinci/CollectorInitializer.kt (1)

22-26: 🗄️ Data Integrity & Integration | 🔵 Trivial

Unresolved server-contract TODO.

The registration key "RECOGNIZE" is marked as unconfirmed with the server team. If the actual DaVinci discriminator differs, the collector factory silently fails to dispatch this component.

Do you want me to open a tracking issue for confirming this value before release?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@recognize/src/main/kotlin/com/pingidentity/recognize/davinci/CollectorInitializer.kt`
around lines 22 - 26, Resolve the server-contract TODO in
CollectorInitializer.create by confirming the DaVinci component discriminator
with the server team and updating the CollectorFactory.register key to the
verified value. Remove the TODO once confirmed, while preserving registration of
RecognizeCollector and returning CollectorFactory.
recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeAuthenticateCollector.kt (1)

75-159: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Significant boilerplate overlap with RecognizeEnrollCollector.collect().

SetupConfig construction, OperationInfo parsing (lines 87-96), ClientStateType mapping (lines 99-102), and JwtSigningInfo building (lines 106-110) are near-identical to the equivalent blocks in RecognizeEnrollCollector.kt. Consider extracting these as protected helpers on AbstractRecognizeCollector to avoid drift as more operation types are added.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeAuthenticateCollector.kt`
around lines 75 - 159, Extract the duplicated SetupConfig construction,
OperationInfo parsing, ClientStateType mapping, and JwtSigningInfo creation from
RecognizeAuthenticateCollector.collect() and RecognizeEnrollCollector.collect()
into protected helpers on AbstractRecognizeCollector. Update both collectors to
reuse those helpers while preserving their current inputs, defaults, and
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@recognize/build.gradle.kts`:
- Around line 25-29: Replace the string-literal project dependencies in
recognize/build.gradle.kts lines 25-29 with the specified typesafe accessors:
projects.foundation.utils, projects.foundation.logger,
projects.foundation.android, projects.foundation.davinciPlugin, and
projects.foundation.journeyPlugin. Also update
samples/pingsampleapp/build.gradle.kts line 92 from project(":recognize") to
projects.recognize.

In
`@recognize/src/main/kotlin/com/pingidentity/recognize/journey/AbstractRecognizeCallback.kt`:
- Around line 176-191: Update setValueCallback in AbstractRecognizeCallback to
use an exact suffix check with callback.id.endsWith(idSuffix) instead of
substring matching via contains. Preserve the existing ValueCallback filtering
and value assignment so CLIENT_ERROR_SUFFIX and CLIENT_ERROR_CODE_SUFFIX work
independently of update order.
- Around line 101-118: Guard the first-element access for server-supplied
MetadataCallback output arrays so empty arrays become a no-op rather than
throwing. In AbstractRecognizeCallback.init, replace the direct output[0] access
with a safe first-element lookup; apply the same firstOrNull handling to
jsonObject["output"] in RecognizeCallback. Update both listed sites:
recognize/src/main/kotlin/com/pingidentity/recognize/journey/AbstractRecognizeCallback.kt
lines 101-118 and
recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeCallback.kt
lines 66-92.

In
`@recognize/src/test/kotlin/com/pingidentity/recognize/davinci/CollectorInitializerTest.kt`:
- Around line 20-23: Add an `@AfterTest` cleanup method in
CollectorInitializerTest that calls CollectorFactory.reset() after each test,
while preserving the existing `@BeforeTest` setup reset. Ensure the global
CollectorFactory registry is cleared even when tests run in different orders.

In
`@samples/pingsampleapp/src/main/java/com/pingidentity/samples/pingsampleapp/journey/callback/JourneyContinueNode.kt`:
- Around line 176-185: Update the LaunchedEffect handlers for
PingOneRecognizeEnrollCallback and PingOneRecognizeAuthenticateCallback to
advance via onNext only when enroll() or authenticate() returns a successful
Result; preserve showNext = false and allow failures to remain on the current
journey step.

In `@settings.gradle.kts`:
- Around line 18-29: The top-level Cloudsmith token delegates in
settings.gradle.kts fail configuration when contributors have not defined the
properties. Update the settings initialization around cloudsmithTokenRecognize
and cloudsmithTokenAesWrap to use graceful optional fallbacks, and ensure the
Cloudsmith repository configuration remains valid without tokens so Gradle sync
and CI can proceed for all contributors.

---

Nitpick comments:
In
`@recognize/src/main/kotlin/com/pingidentity/recognize/davinci/AbstractRecognizeCollector.kt`:
- Line 28: Change AbstractRecognizeCollector to internal visibility, and update
any directly declared subclasses if needed to satisfy Kotlin visibility rules.
Keep the CollectorFactory.register integration and documented public API
unchanged.

In
`@recognize/src/main/kotlin/com/pingidentity/recognize/davinci/CollectorInitializer.kt`:
- Around line 22-26: Resolve the server-contract TODO in
CollectorInitializer.create by confirming the DaVinci component discriminator
with the server team and updating the CollectorFactory.register key to the
verified value. Remove the TODO once confirmed, while preserving registration of
RecognizeCollector and returning CollectorFactory.

In
`@recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeAuthenticateCollector.kt`:
- Around line 75-159: Extract the duplicated SetupConfig construction,
OperationInfo parsing, ClientStateType mapping, and JwtSigningInfo creation from
RecognizeAuthenticateCollector.collect() and RecognizeEnrollCollector.collect()
into protected helpers on AbstractRecognizeCollector. Update both collectors to
reuse those helpers while preserving their current inputs, defaults, and
behavior.

In
`@recognize/src/test/kotlin/com/pingidentity/recognize/davinci/CollectorInitializerTest.kt`:
- Around line 25-33: Update the test create registers RECOGNIZE collector and
returns factory to invoke the registered "RECOGNIZE" entry through the
CollectorFactory API, then assert the produced collector is a
RecognizeCollector. Replace the insufficient assertNotNull check while
preserving the existing factory identity assertion.

In
`@recognize/src/test/kotlin/com/pingidentity/recognize/journey/RecognizeCallbackTest.kt`:
- Around line 84-104: Extract a shared JSON-builder helper for the repeated
callback payloads in RecognizeCallbackTest, following the authInput pattern from
RecognizeAuthenticateCollectorTest. Give it named defaults for common fields and
an optional mobileSDKOptions builder, then update metadataCallbackJson and the
referenced test payload builders to use it while keeping each test’s variable
fields explicit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 73b74d2c-3a60-4b48-adcd-41425e3735d9

📥 Commits

Reviewing files that changed from the base of the PR and between 5f1e47f and 9c8a809.

📒 Files selected for processing (30)
  • CHANGELOG.md
  • gradle/libs.versions.toml
  • recognize/README.md
  • recognize/build.gradle.kts
  • recognize/src/main/AndroidManifest.xml
  • recognize/src/main/kotlin/com/pingidentity/recognize/Recognize.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/RecognizeException.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/RecognizeSuccess.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/AbstractRecognizeCollector.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/CollectorInitializer.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeAuthenticateCollector.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeCollector.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeEnrollCollector.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/AbstractRecognizeCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/CallbackInitializer.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeEnrollCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeKeylessInitializer.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/RecognizeExceptionTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/RecognizeTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/CollectorInitializerTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/RecognizeAuthenticateCollectorTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/RecognizeCollectorTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/RecognizeEnrollCollectorTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/journey/CallbackInitializerTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/journey/RecognizeCallbackTest.kt
  • samples/pingsampleapp/build.gradle.kts
  • samples/pingsampleapp/src/main/java/com/pingidentity/samples/pingsampleapp/journey/callback/JourneyContinueNode.kt
  • settings.gradle.kts

Comment thread recognize/build.gradle.kts
Comment thread settings.gradle.kts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeCallback.kt (1)

37-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Declare the documented callback class explicitly as public.

Line 37 is a documented, registry-facing API. Add explicit visibility for consistency with the project API guidelines.

Proposed fix
-class RecognizeCallback : AbstractCallback() {
+public class RecognizeCallback : AbstractCallback() {

As per coding guidelines, declare public explicitly on the documented API surface.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeCallback.kt`
at line 37, Update the RecognizeCallback class declaration to explicitly use
public visibility, preserving its existing inheritance from AbstractCallback and
registry-facing API behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Line 2: Update the “Added” heading in the Unreleased changelog section from h4
to h3, changing “#### Added” to “### Added” while preserving the surrounding
changelog content.

In
`@recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeCallback.kt`:
- Around line 58-60: Update the MetadataCallback documentation near
AbstractRecognizeCallback.init to describe operationType at
output[0].value.operationType, removing the incorrect .data segment while
preserving the delegation description.
- Around line 66-73: Update RecognizeCallback.init to safely read the first
MetadataCallback output entry without indexing an empty jsonArray, allowing the
documented IllegalArgumentException validation to handle missing output. Add a
regression test covering a MetadataCallback with an empty output array.

---

Nitpick comments:
In
`@recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeCallback.kt`:
- Line 37: Update the RecognizeCallback class declaration to explicitly use
public visibility, preserving its existing inheritance from AbstractCallback and
registry-facing API behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 144214b5-3a7a-4bd4-a863-793765f088e6

📥 Commits

Reviewing files that changed from the base of the PR and between 9c8a809 and a0d3a77.

📒 Files selected for processing (30)
  • CHANGELOG.md
  • gradle/libs.versions.toml
  • recognize/README.md
  • recognize/build.gradle.kts
  • recognize/src/main/AndroidManifest.xml
  • recognize/src/main/kotlin/com/pingidentity/recognize/Recognize.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/RecognizeException.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/RecognizeSuccess.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/AbstractRecognizeCollector.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/CollectorInitializer.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeAuthenticateCollector.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeCollector.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeEnrollCollector.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/AbstractRecognizeCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/CallbackInitializer.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeEnrollCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeKeylessInitializer.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/RecognizeExceptionTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/RecognizeTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/CollectorInitializerTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/RecognizeAuthenticateCollectorTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/RecognizeCollectorTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/RecognizeEnrollCollectorTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/journey/CallbackInitializerTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/journey/RecognizeCallbackTest.kt
  • samples/pingsampleapp/build.gradle.kts
  • samples/pingsampleapp/src/main/java/com/pingidentity/samples/pingsampleapp/journey/callback/JourneyContinueNode.kt
  • settings.gradle.kts
🚧 Files skipped from review as they are similar to previous changes (28)
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/CollectorInitializer.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/CollectorInitializerTest.kt
  • samples/pingsampleapp/build.gradle.kts
  • recognize/src/main/AndroidManifest.xml
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeCollector.kt
  • recognize/build.gradle.kts
  • recognize/src/main/kotlin/com/pingidentity/recognize/RecognizeException.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/CallbackInitializer.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/RecognizeSuccess.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/RecognizeExceptionTest.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeKeylessInitializer.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/RecognizeCollectorTest.kt
  • gradle/libs.versions.toml
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeEnrollCallback.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/RecognizeTest.kt
  • settings.gradle.kts
  • samples/pingsampleapp/src/main/java/com/pingidentity/samples/pingsampleapp/journey/callback/JourneyContinueNode.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/AbstractRecognizeCollector.kt
  • recognize/README.md
  • recognize/src/test/kotlin/com/pingidentity/recognize/journey/CallbackInitializerTest.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeAuthenticateCollector.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/davinci/RecognizeEnrollCollector.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/RecognizeEnrollCollectorTest.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/davinci/RecognizeAuthenticateCollectorTest.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/AbstractRecognizeCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/Recognize.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/journey/RecognizeCallbackTest.kt

Comment thread CHANGELOG.md
Comment thread recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeCallback.kt Outdated
Comment thread recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeCallback.kt Outdated
*
* @return [Result] containing [RecognizeSuccess] on success, or a [Throwable] on failure.
*/
suspend fun enroll(retrieveSelfie: Boolean = false): Result<RecognizeSuccess> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Instead of providing the retrieveSelfie as parameter, do you want to create an config object instead? (reference:

suspend fun bind(config: DeviceBindingConfig.() -> Unit = {}): Result<String> = runCatching {
)
With object, allow more flexibility to add more customization in the future.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

yeah, I can totally do it this way 👍

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Addressed here

let me know if as expected 👍

keylessId = success.keylessId,
)
}
.recoverCatching { throw it as RecognizeException }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is it possible that the exception is not a RecognizeException? that will result with ClassCastExcetpion?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

So, the exception at that point should always be correct, tho, it is not compiler safe.

Also this recoverCatching is actually redundant, so I removed it and just adopted a more lenient converstion from the throwable in this commit so that no casting issue will occurr (they shoudn't have occurred already logically but due to an absent compile time guarantee, this will make us safer against unexpected code changes or bugs that might actually trigger an unexpected throwable.

Let me know if this fix is good enough for this, i tried avoiding a custom Result.Failure or similar since it becomes an heavier change and forces the integrator to then handle it with a when statement, while the kotlin Result is idiomatic and preferred.

…gnize callbacks

Introduce RecognizeEnrollConfig and RecognizeAuthenticateConfig so enroll/authenticate
accept a lambda-with-receiver instead of a flat Boolean, matching the DeviceBindingConfig
pattern and allowing future options without API breaks.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt (1)

91-101: 🩺 Stability & Availability | 🟠 Major

Preserve non-RecognizeException failures.

onFailure receives a general Throwable, but both callbacks cast every failure to RecognizeException. Any unexpected SDK or setup failure becomes a ClassCastException, masking the original error and preventing Journey error submission. Normalize failures safely or preserve the original Throwable, including in recoverCatching.

  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt#L91-L101: remove the unchecked casts in failure mapping and recovery.
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeEnrollCallback.kt#L68-L86: apply the same safe failure handling.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt`
around lines 91 - 101, Remove the unchecked RecognizeException casts in the
failure mapping and recovery of
recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt
lines 91-101, preserving non-RecognizeException Throwables while still
submitting appropriate Journey error details. Apply the same safe failure
handling in
recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeEnrollCallback.kt
lines 68-86, including its recoverCatching path.
🧹 Nitpick comments (1)
recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt (1)

62-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Declare exported APIs explicitly as public.

These documented APIs currently rely on Kotlin’s implicit public visibility. Add explicit public modifiers to the callback methods, configuration classes, and retrieveSelfie properties.

  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt#L62-L62: declare authenticate public.
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeEnrollCallback.kt#L52-L52: declare enroll public.
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeConfig.kt#L22-L25: declare RecognizeEnrollConfig and retrieveSelfie public.
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeConfig.kt#L38-L41: declare RecognizeAuthenticateConfig and retrieveSelfie public.

As per coding guidelines, documented public APIs must declare public explicitly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt`
at line 62, Declare the documented APIs explicitly as public: make authenticate
public in PingOneRecognizeAuthenticateCallback.kt (line 62), enroll public in
PingOneRecognizeEnrollCallback.kt (line 52), and make RecognizeEnrollConfig,
RecognizeAuthenticateConfig, and both retrieveSelfie properties public in
RecognizeConfig.kt (lines 22-25 and 38-41).

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt`:
- Around line 91-101: Remove the unchecked RecognizeException casts in the
failure mapping and recovery of
recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt
lines 91-101, preserving non-RecognizeException Throwables while still
submitting appropriate Journey error details. Apply the same safe failure
handling in
recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeEnrollCallback.kt
lines 68-86, including its recoverCatching path.

---

Nitpick comments:
In
`@recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt`:
- Line 62: Declare the documented APIs explicitly as public: make authenticate
public in PingOneRecognizeAuthenticateCallback.kt (line 62), enroll public in
PingOneRecognizeEnrollCallback.kt (line 52), and make RecognizeEnrollConfig,
RecognizeAuthenticateConfig, and both retrieveSelfie properties public in
RecognizeConfig.kt (lines 22-25 and 38-41).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ae1efb16-374f-4a90-b1aa-3e69d35ce8b6

📥 Commits

Reviewing files that changed from the base of the PR and between a0d3a77 and 1de0cdd.

📒 Files selected for processing (3)
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeEnrollCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeConfig.kt

mariodigirolamo1 and others added 4 commits July 30, 2026 15:19
…ognize callbacks

Remove the dead `recoverCatching` lines and replace the unchecked `error as RecognizeException`
casts in `onFailure` with `asRecognizeException()`, an internal extension that returns the
exception as-is if it is already a `RecognizeException`, or wraps any unexpected `Throwable`
with code=-1 and the original as cause rather than crashing.
Signed-off-by: Mario Di Girolamo <69394590+mariodigirolamo1@users.noreply.github.com>
…tegration

Journey's MetadataCallback router only dispatches to Protect and FIDO;
Recognize data hits the else branch and is silently dropped, making
the ContinueNodeAware, continueNode, derivedCallback, setValueCallback,
and companion object suffix constants unreachable dead code.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
samples/pingsampleapp/build.gradle.kts (1)

90-90: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the typesafe project accessor.

Replace implementation(project(":recognize")) with implementation(projects.recognize). As per coding guidelines, use typesafe project accessors instead of string literals in build.gradle.kts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@samples/pingsampleapp/build.gradle.kts` at line 90, Update the dependency
declaration in the Gradle configuration to use the typesafe projects accessor
projects.recognize instead of the string-based project(":recognize") reference,
leaving the implementation dependency unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@samples/pingsampleapp/build.gradle.kts`:
- Line 90: Update the dependency declaration in the Gradle configuration to use
the typesafe projects accessor projects.recognize instead of the string-based
project(":recognize") reference, leaving the implementation dependency
unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8f7a5180-8a2d-4523-8b3c-37cac9c11af1

📥 Commits

Reviewing files that changed from the base of the PR and between 1de0cdd and 5a9b911.

📒 Files selected for processing (8)
  • gradle/libs.versions.toml
  • recognize/src/main/kotlin/com/pingidentity/recognize/RecognizeException.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/AbstractRecognizeCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeAuthenticateCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/PingOneRecognizeEnrollCallback.kt
  • recognize/src/main/kotlin/com/pingidentity/recognize/journey/RecognizeCallback.kt
  • recognize/src/test/kotlin/com/pingidentity/recognize/journey/RecognizeCallbackTest.kt
  • samples/pingsampleapp/build.gradle.kts

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.

2 participants