Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tired-melons-wish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@forgerock/davinci-client': minor
---

Added WebAuthn/FIDO2 collectors
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@
"shx": "^0.4.0",
"swc-loader": "0.2.6",
"ts-node": "10.9.2",
"tslib": "^2.5.0",
"ts-patch": "3.3.0",
"tslib": "^2.5.0",
"typedoc": "^0.27.4",
"typedoc-github-theme": "0.2.1",
"typedoc-plugin-rename-defaults": "^0.7.2",
Expand Down
30 changes: 23 additions & 7 deletions packages/davinci-client/src/lib/client.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import type {
PhoneNumberInputValue,
AutoCollectors,
MultiValueCollectors,
FidoRegistrationInputValue,
FidoAuthenticationInputValue,
} from './collector.types.js';
import type {
InitFlow,
Expand Down Expand Up @@ -266,16 +268,25 @@ export async function davinci<ActionType extends ActionTypes = ActionTypes>({
collectorToUpdate.category !== 'SingleValueCollector' &&
collectorToUpdate.category !== 'ValidatedSingleValueCollector' &&
collectorToUpdate.category !== 'ObjectValueCollector' &&
collectorToUpdate.category !== 'SingleValueAutoCollector'
collectorToUpdate.category !== 'SingleValueAutoCollector' &&
collectorToUpdate.category !== 'ObjectValueAutoCollector'
) {
return handleUpdateValidateError(
'Collector is not a MultiValueCollector, SingleValueCollector, ValidatedSingleValueCollector, ObjectValueCollector, or SingleValueAutoCollector and cannot be updated',
'Collector does not fall into a category that can be updated',
'state_error',
log.error,
);
}

return function (value: string | string[] | PhoneNumberInputValue, index?: number) {
return function (
value:
| string
| string[]
| PhoneNumberInputValue
| FidoRegistrationInputValue
| FidoAuthenticationInputValue,
index?: number,
) {
try {
store.dispatch(nodeSlice.actions.update({ id, value, index }));
return null;
Expand All @@ -291,12 +302,16 @@ export async function davinci<ActionType extends ActionTypes = ActionTypes>({

/**
* @method validate - Method for validating the value against validation rules
* @param {SingleValueCollectors | ObjectValueCollectors | MultiValueCollectors} collector - the collector to validate
* @param {SingleValueCollectors | ObjectValueCollectors | MultiValueCollectors | AutoCollectors} collector - the collector to validate
* @returns {function} - a function to call for validating collector value
* @throws {Error} - if the collector cannot be validated
*/
validate: (
collector: SingleValueCollectors | ObjectValueCollectors | MultiValueCollectors,
collector:
| SingleValueCollectors
| ObjectValueCollectors
| MultiValueCollectors
| AutoCollectors,
): Validator => {
if (!collector.id) {
return handleUpdateValidateError(
Expand All @@ -323,10 +338,11 @@ export async function davinci<ActionType extends ActionTypes = ActionTypes>({
if (
collectorToUpdate.category !== 'ValidatedSingleValueCollector' &&
collectorToUpdate.category !== 'ObjectValueCollector' &&
collectorToUpdate.category !== 'MultiValueCollector'
collectorToUpdate.category !== 'MultiValueCollector' &&
collectorToUpdate.category !== 'ObjectValueAutoCollector'
) {
return handleUpdateValidateError(
'Collector is not a SingleValueCollector, ObjectValueCollector, or MultiValueCollector and cannot be validated',
'Collector does not fall into a category that can be validated',
'state_error',
log.error,
);
Expand Down
1 change: 1 addition & 0 deletions packages/davinci-client/src/lib/collector.types.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ describe('Collector Types', () => {
key: '',
value: [''],
type: '',
validation: null,
},
output: {
key: '',
Expand Down
70 changes: 55 additions & 15 deletions packages/davinci-client/src/lib/collector.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export interface MultiValueCollectorWithValue<T extends MultiValueCollectorTypes
key: string;
value: string[];
type: string;
validation?: ValidationRequired[];
validation: ValidationRequired[] | null;
};
output: {
key: string;
Expand All @@ -223,7 +223,7 @@ export interface MultiValueCollectorNoValue<T extends MultiValueCollectorTypes>
key: string;
value: string[];
type: string;
validation?: ValidationRequired[];
validation: ValidationRequired[] | null;
};
output: {
key: string;
Expand Down Expand Up @@ -302,6 +302,14 @@ export interface PhoneNumberOutputValue {
phoneNumber?: string;
}

export interface FidoRegistrationInputValue {
attestationValue?: PublicKeyCredential;
}

export interface FidoAuthenticationInputValue {
assertionValue?: PublicKeyCredential;
}

export interface ObjectOptionsCollectorWithStringValue<
T extends ObjectValueCollectorTypes,
V = string,
Expand All @@ -315,7 +323,7 @@ export interface ObjectOptionsCollectorWithStringValue<
key: string;
value: V;
type: string;
validation?: ValidationRequired[];
validation: ValidationRequired[] | null;
};
output: {
key: string;
Expand All @@ -339,7 +347,7 @@ export interface ObjectOptionsCollectorWithObjectValue<
key: string;
value: V;
type: string;
validation?: ValidationRequired[];
validation: ValidationRequired[] | null;
};
output: {
key: string;
Expand All @@ -364,7 +372,7 @@ export interface ObjectValueCollectorWithObjectValue<
key: string;
value: IV;
type: string;
validation?: (ValidationRequired | ValidationPhoneNumber)[];
validation: (ValidationRequired | ValidationPhoneNumber)[] | null;
};
output: {
key: string;
Expand Down Expand Up @@ -536,13 +544,18 @@ export type UnknownCollector = {
* @interface AutoCollector - Represents a collector that collects a value programmatically without user intervention.
*/

export type AutoCollectorCategories = 'SingleValueAutoCollector';
export type AutoCollectorTypes = AutoCollectorCategories | 'ProtectCollector';
export type AutoCollectorCategories = 'SingleValueAutoCollector' | 'ObjectValueAutoCollector';
export type SingleValueAutoCollectorTypes = 'SingleValueAutoCollector' | 'ProtectCollector';
export type ObjectValueAutoCollectorTypes =
| 'ObjectValueAutoCollector'
| 'FidoRegistrationCollector'
| 'FidoAuthenticationCollector';
export type AutoCollectorTypes = SingleValueAutoCollectorTypes | ObjectValueAutoCollectorTypes;

export interface AutoCollector<
C extends AutoCollectorCategories,
T extends AutoCollectorTypes,
V = string,
IV = string,
> {
category: C;
error: string | null;
Expand All @@ -551,8 +564,9 @@ export interface AutoCollector<
name: string;
input: {
key: string;
value: V;
value: IV;
type: string;
validation?: ValidationRequired[] | null;
};
output: {
key: string;
Expand All @@ -566,13 +580,33 @@ export type ProtectCollector = AutoCollector<
'ProtectCollector',
string
>;
export type FidoRegistrationCollector = AutoCollector<
'ObjectValueAutoCollector',
'FidoRegistrationCollector',
FidoRegistrationInputValue
>;
export type FidoAuthenticationCollector = AutoCollector<
'ObjectValueAutoCollector',
'FidoAuthenticationCollector',
FidoAuthenticationInputValue
>;
export type SingleValueAutoCollector = AutoCollector<
'SingleValueAutoCollector',
'SingleValueAutoCollector',
string
>;
export type ObjectValueAutoCollector = AutoCollector<
'ObjectValueAutoCollector',
'ObjectValueAutoCollector',
Record<string, unknown>
>;

export type AutoCollectors = ProtectCollector | SingleValueAutoCollector;
export type AutoCollectors =
| ProtectCollector
| FidoRegistrationCollector
| FidoAuthenticationCollector
| SingleValueAutoCollector
| ObjectValueAutoCollector;

Comment on lines +604 to 610
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Public re-exports check for new AutoCollectors

Verify the package’s public barrel (src/types.ts or equivalent) re-exports FidoRegistrationCollector, FidoAuthenticationCollector, and ObjectValueAutoCollector so app consumers don’t import from internal paths.

Also applies to: 618-630


🏁 Script executed:

#!/bin/bash
# Look for public re-exports of FIDO collectors
rg -nP --glob "packages/davinci-client/src/types.ts" \
  -C2 "Fido(Reg|Auth)enticationCollector|ObjectValueAutoCollector"

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check if types.ts exists at the specified path
if [ -f "packages/davinci-client/src/types.ts" ]; then
  echo "=== types.ts EXISTS ==="
  echo "First 50 lines:"
  head -50 "packages/davinci-client/src/types.ts"
else
  echo "=== types.ts NOT FOUND at packages/davinci-client/src/types.ts ==="
  echo "Searching for public barrel files:"
  fd -e ts -e js "types|index|barrel" "packages/davinci-client/src" | grep -E "(types|index|barrel)" | head -20
fi

Length of output: 2514


🏁 Script executed:

#!/bin/bash
# Find package.json and check export configuration
if [ -f "packages/davinci-client/package.json" ]; then
  echo "=== package.json exports field ==="
  jq '.exports // "No exports field"' "packages/davinci-client/package.json"
fi

Length of output: 105


🏁 Script executed:

#!/bin/bash
# Search for where AutoCollectors or the new collector types are exported
echo "=== Searching for re-exports of new collectors ==="
rg -nP "export.*?(FidoRegistration|FidoAuthentication|ObjectValueAutoCollector|AutoCollectors)" "packages/davinci-client/src" -C2

Length of output: 6563


🏁 Script executed:

#!/bin/bash
# View complete types.ts to see all exports
wc -l "packages/davinci-client/src/types.ts"
echo "=== Last 100 lines of types.ts ==="
tail -100 "packages/davinci-client/src/types.ts"

Length of output: 2711


🏁 Script executed:

#!/bin/bash
# Explicitly search for AutoCollectors export in types.ts
echo "=== Checking for AutoCollectors in types.ts ==="
grep -n "AutoCollectors\|FidoRegistrationCollector\|FidoAuthenticationCollector\|ObjectValueAutoCollector" "packages/davinci-client/src/types.ts" || echo "No matches found"

Length of output: 64


Missing public re-exports for new AutoCollector types

The new collector types (FidoRegistrationCollector, FidoAuthenticationCollector, ObjectValueAutoCollector, and the AutoCollectors union) defined in collector.types.ts (lines 604–610) are not re-exported in the public barrel file (packages/davinci-client/src/types.ts).

App consumers will be forced to import directly from internal paths instead of the public API. Add these exports to types.ts following the existing pattern (e.g., export type FidoRegistrationCollector = collectors.FidoRegistrationCollector;).

🤖 Prompt for AI Agents
In packages/davinci-client/src/types.ts (add near the other collector
re-exports), export the new types from the internal collectors namespace: add
type re-exports for FidoRegistrationCollector, FidoAuthenticationCollector,
ObjectValueAutoCollector, and the AutoCollectors union following the existing
pattern (e.g., export type FidoRegistrationCollector =
collectors.FidoRegistrationCollector;). Ensure the file imports or references
the collectors namespace already used by other collector re-exports and place
the new lines next to those to keep public API consistent.

/**
* Type to help infer the collector based on the collector type
Expand All @@ -583,8 +617,14 @@ export type AutoCollectors = ProtectCollector | SingleValueAutoCollector;
*/
export type InferAutoCollectorType<T extends AutoCollectorTypes> = T extends 'ProtectCollector'
? ProtectCollector
: /**
* At this point, we have not passed in a collector type
* so we can return a SingleValueAutoCollector
**/
SingleValueAutoCollector;
: T extends 'FidoRegistrationCollector'
? FidoRegistrationCollector
: T extends 'FidoAuthenticationCollector'
? FidoAuthenticationCollector
: T extends 'ObjectValueAutoCollector'
? ObjectValueAutoCollector
: /**
* At this point, we have not passed in a collector type
* so we can return a SingleValueAutoCollector
**/
SingleValueAutoCollector;
Loading
Loading