@smileid/usesmileid 12.0.0 → 12.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +1 -1
- package/dist/camera/camera_defaults.d.ts +2 -0
- package/dist/camera/camera_defaults.d.ts.map +1 -1
- package/dist/camera/camera_defaults.js +2 -0
- package/dist/camera/camera_defaults.js.map +1 -1
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.d.ts +11 -0
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.d.ts.map +1 -0
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.js +17 -0
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.js.map +1 -0
- package/dist/core/exception/capture_validation_exceptions.d.ts +1 -0
- package/dist/core/exception/capture_validation_exceptions.d.ts.map +1 -1
- package/dist/core/exception/capture_validation_exceptions.js +1 -0
- package/dist/core/exception/capture_validation_exceptions.js.map +1 -1
- package/dist/core/exception/flow_exceptions.d.ts +4 -2
- package/dist/core/exception/flow_exceptions.d.ts.map +1 -1
- package/dist/core/exception/flow_exceptions.js +3 -2
- package/dist/core/exception/flow_exceptions.js.map +1 -1
- package/dist/core/exception/index.d.ts +1 -0
- package/dist/core/exception/index.d.ts.map +1 -1
- package/dist/core/exception/index.js +1 -0
- package/dist/core/exception/index.js.map +1 -1
- package/dist/core/exception/missing_job_type_exception.d.ts +1 -3
- package/dist/core/exception/missing_job_type_exception.d.ts.map +1 -1
- package/dist/core/exception/missing_job_type_exception.js +2 -4
- package/dist/core/exception/missing_job_type_exception.js.map +1 -1
- package/dist/core/exception/use_smile_id_error_code.d.ts +1 -0
- package/dist/core/exception/use_smile_id_error_code.d.ts.map +1 -1
- package/dist/core/exception/use_smile_id_error_code.js +1 -0
- package/dist/core/exception/use_smile_id_error_code.js.map +1 -1
- package/dist/core/models/config.d.ts +19 -0
- package/dist/core/models/config.d.ts.map +1 -1
- package/dist/core/models/document_type.d.ts +1 -1
- package/dist/core/models/document_type.d.ts.map +1 -1
- package/dist/core/models/document_type.js +2 -2
- package/dist/core/models/document_type.js.map +1 -1
- package/dist/core/models/global_privacy_control.d.ts +36 -0
- package/dist/core/models/global_privacy_control.d.ts.map +1 -0
- package/dist/core/models/global_privacy_control.js +39 -0
- package/dist/core/models/global_privacy_control.js.map +1 -0
- package/dist/core/models/network_config.d.ts +2 -2
- package/dist/core/models/network_config.js +2 -2
- package/dist/data/api/interceptors/smile_auth_interceptor.d.ts.map +1 -1
- package/dist/data/api/interceptors/smile_auth_interceptor.js +3 -17
- package/dist/data/api/interceptors/smile_auth_interceptor.js.map +1 -1
- package/dist/data/api/smile_id_api.d.ts +5 -1
- package/dist/data/api/smile_id_api.d.ts.map +1 -1
- package/dist/data/api/smile_id_api.js +30 -27
- package/dist/data/api/smile_id_api.js.map +1 -1
- package/dist/data/dsl/builder/retry_config_builder.d.ts +4 -4
- package/dist/data/dsl/builder/retry_config_builder.d.ts.map +1 -1
- package/dist/data/dsl/builder/retry_config_builder.js +6 -6
- package/dist/data/dsl/builder/retry_config_builder.js.map +1 -1
- package/dist/data/model/job_request.d.ts +28 -12
- package/dist/data/model/job_request.d.ts.map +1 -1
- package/dist/data/model/token_payload.d.ts +78 -0
- package/dist/data/model/token_payload.d.ts.map +1 -0
- package/dist/data/model/token_payload.js +132 -0
- package/dist/data/model/token_payload.js.map +1 -0
- package/dist/data/model/user_details_payload.d.ts +39 -0
- package/dist/data/model/user_details_payload.d.ts.map +1 -0
- package/dist/data/model/user_details_payload.js +53 -0
- package/dist/data/model/user_details_payload.js.map +1 -0
- package/dist/data/smile_id_urls.d.ts +1 -1
- package/dist/data/smile_id_urls.js +1 -1
- package/dist/data/smile_id_urls.js.map +1 -1
- package/dist/data/util/retry_util.d.ts +1 -1
- package/dist/data/util/retry_util.d.ts.map +1 -1
- package/dist/data/util/retry_util.js +5 -0
- package/dist/data/util/retry_util.js.map +1 -1
- package/dist/data/util/use_smile_id_token_decoder.d.ts +15 -3
- package/dist/data/util/use_smile_id_token_decoder.d.ts.map +1 -1
- package/dist/data/util/use_smile_id_token_decoder.js +20 -8
- package/dist/data/util/use_smile_id_token_decoder.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/l10n/strings_en.d.ts +4 -1
- package/dist/l10n/strings_en.d.ts.map +1 -1
- package/dist/l10n/strings_en.js +4 -1
- package/dist/l10n/strings_en.js.map +1 -1
- package/dist/l10n/use_smile_id_localizations.d.ts +10 -0
- package/dist/l10n/use_smile_id_localizations.d.ts.map +1 -1
- package/dist/l10n/use_smile_id_localizations.js +59 -3
- package/dist/l10n/use_smile_id_localizations.js.map +1 -1
- package/dist/metadata/builder_configuration.d.ts +5 -0
- package/dist/metadata/builder_configuration.d.ts.map +1 -1
- package/dist/metadata/builder_configuration.js +1 -0
- package/dist/metadata/builder_configuration.js.map +1 -1
- package/dist/metadata/metadata_configuration_mappers.d.ts +2 -3
- package/dist/metadata/metadata_configuration_mappers.d.ts.map +1 -1
- package/dist/metadata/metadata_configuration_mappers.js +13 -6
- package/dist/metadata/metadata_configuration_mappers.js.map +1 -1
- package/dist/metadata/use_smile_id_metadata_factory.d.ts.map +1 -1
- package/dist/metadata/use_smile_id_metadata_factory.js +14 -5
- package/dist/metadata/use_smile_id_metadata_factory.js.map +1 -1
- package/dist/presentation/components/use_smile_id_button.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_button.js +8 -2
- package/dist/presentation/components/use_smile_id_button.js.map +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts +5 -2
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js +8 -3
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js.map +1 -1
- package/dist/presentation/components/use_smile_id_instructions_hero.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_instructions_hero.js +8 -3
- package/dist/presentation/components/use_smile_id_instructions_hero.js.map +1 -1
- package/dist/presentation/flow/dsl/builder/config_builder.d.ts +16 -0
- package/dist/presentation/flow/dsl/builder/config_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/builder/config_builder.js +18 -0
- package/dist/presentation/flow/dsl/builder/config_builder.js.map +1 -1
- package/dist/presentation/flow/dsl/builder/screens_builder.d.ts +6 -12
- package/dist/presentation/flow/dsl/builder/screens_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/builder/screens_builder.js +7 -12
- package/dist/presentation/flow/dsl/builder/screens_builder.js.map +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js +23 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js.map +1 -1
- package/dist/presentation/flow/flow_navigation_manager.d.ts +22 -3
- package/dist/presentation/flow/flow_navigation_manager.d.ts.map +1 -1
- package/dist/presentation/flow/flow_navigation_manager.js +84 -46
- package/dist/presentation/flow/flow_navigation_manager.js.map +1 -1
- package/dist/presentation/flow/model/instructions_defaults.d.ts.map +1 -1
- package/dist/presentation/flow/model/instructions_defaults.js +1 -1
- package/dist/presentation/flow/model/instructions_defaults.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_capture_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_capture_screen.js +13 -3
- package/dist/presentation/flow/screen/orchestrated_capture_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_consent_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_consent_screen.js +3 -1
- package/dist/presentation/flow/screen/orchestrated_consent_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_preview_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_preview_screen.js +0 -8
- package/dist/presentation/flow/screen/orchestrated_preview_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_processing_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_processing_screen.js +25 -5
- package/dist/presentation/flow/screen/orchestrated_processing_screen.js.map +1 -1
- package/dist/presentation/flow/use_smile_id_flow.d.ts.map +1 -1
- package/dist/presentation/flow/use_smile_id_flow.js +45 -12
- package/dist/presentation/flow/use_smile_id_flow.js.map +1 -1
- package/dist/presentation/flow/validation/flow_validator.d.ts +16 -2
- package/dist/presentation/flow/validation/flow_validator.d.ts.map +1 -1
- package/dist/presentation/flow/validation/flow_validator.js +61 -47
- package/dist/presentation/flow/validation/flow_validator.js.map +1 -1
- package/dist/presentation/flow/validation/job_type_validator.d.ts +7 -0
- package/dist/presentation/flow/validation/job_type_validator.d.ts.map +1 -1
- package/dist/presentation/flow/validation/job_type_validator.js +52 -27
- package/dist/presentation/flow/validation/job_type_validator.js.map +1 -1
- package/dist/presentation/flow/validation/user_details_validator.d.ts +9 -0
- package/dist/presentation/flow/validation/user_details_validator.d.ts.map +1 -0
- package/dist/presentation/flow/validation/user_details_validator.js +40 -0
- package/dist/presentation/flow/validation/user_details_validator.js.map +1 -0
- package/dist/presentation/screen/helpers/capture_screen_helpers.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/capture_screen_helpers.js +1 -0
- package/dist/presentation/screen/helpers/capture_screen_helpers.js.map +1 -1
- package/dist/presentation/screen/helpers/capture_ui_state.d.ts +6 -6
- package/dist/presentation/screen/helpers/capture_ui_state.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/capture_ui_state.js +19 -19
- package/dist/presentation/screen/helpers/capture_ui_state.js.map +1 -1
- package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts +2 -2
- package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/ess_turn_haptics.js +6 -6
- package/dist/presentation/screen/helpers/ess_turn_haptics.js.map +1 -1
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.d.ts +5 -5
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js +11 -11
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js.map +1 -1
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts +13 -3
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.js +48 -6
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.d.ts +4 -2
- package/dist/presentation/screen/use_smile_id_capture_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.js +90 -23
- package/dist/presentation/screen/use_smile_id_capture_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_consent_screen.d.ts +7 -0
- package/dist/presentation/screen/use_smile_id_consent_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_consent_screen.js +6 -5
- package/dist/presentation/screen/use_smile_id_consent_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_document_back_instructions.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_document_back_instructions.js +5 -13
- package/dist/presentation/screen/use_smile_id_document_back_instructions.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_document_preview_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_document_preview_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_preview_screen.d.ts +1 -21
- package/dist/presentation/screen/use_smile_id_preview_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_preview_screen.js +3 -14
- package/dist/presentation/screen/use_smile_id_preview_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_processing_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_processing_screen.js.map +1 -1
- package/dist/presentation/utils/locale_utils.d.ts +10 -4
- package/dist/presentation/utils/locale_utils.d.ts.map +1 -1
- package/dist/presentation/utils/locale_utils.js +13 -5
- package/dist/presentation/utils/locale_utils.js.map +1 -1
- package/dist/testing/fake_face_analyzer.d.ts +43 -0
- package/dist/testing/fake_face_analyzer.d.ts.map +1 -0
- package/dist/testing/fake_face_analyzer.js +52 -0
- package/dist/testing/fake_face_analyzer.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +7 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/scenario_expectations.d.ts +28 -0
- package/dist/testing/scenario_expectations.d.ts.map +1 -0
- package/dist/testing/scenario_expectations.js +65 -0
- package/dist/testing/scenario_expectations.js.map +1 -0
- package/dist/testing/scenario_loader.d.ts +11 -0
- package/dist/testing/scenario_loader.d.ts.map +1 -0
- package/dist/testing/scenario_loader.js +64 -0
- package/dist/testing/scenario_loader.js.map +1 -0
- package/dist/testing/scripted_scan_results.d.ts +17 -0
- package/dist/testing/scripted_scan_results.d.ts.map +1 -0
- package/dist/testing/scripted_scan_results.js +52 -0
- package/dist/testing/scripted_scan_results.js.map +1 -0
- package/package.json +11 -4
- package/src/__tests__/dsl.test.ts +51 -1
- package/src/__tests__/react_native_mock.tsx +22 -0
- package/src/__tests__/setup_react_native.ts +17 -2
- package/src/__tests__/snapshots/__snapshots__/screens_structural.test.tsx.snap +5267 -0
- package/src/__tests__/snapshots/screens_structural.test.tsx +230 -0
- package/src/camera/__tests__/camera_permissions.test.ts +72 -0
- package/src/camera/__tests__/camera_system_focus.test.ts +173 -0
- package/src/camera/__tests__/use_smile_id_camera_preview.test.tsx +461 -0
- package/src/camera/__tests__/use_smile_id_camera_system.test.ts +103 -0
- package/src/camera/__tests__/use_smile_id_frame_stream_hook.test.tsx +229 -0
- package/src/camera/camera_defaults.ts +3 -0
- package/src/core/exception/__tests__/builder_validation_exceptions.test.ts +81 -0
- package/src/core/exception/agent_mode_with_enhanced_liveness_exception.ts +20 -0
- package/src/core/exception/capture_validation_exceptions.ts +1 -0
- package/src/core/exception/flow_exceptions.test.ts +10 -0
- package/src/core/exception/flow_exceptions.ts +3 -2
- package/src/core/exception/index.ts +1 -0
- package/src/core/exception/missing_job_type_exception.ts +2 -4
- package/src/core/exception/use_smile_id_error_code.ts +1 -0
- package/src/core/models/__tests__/document_type.test.ts +2 -2
- package/src/core/models/__tests__/flow_models.test.ts +26 -0
- package/src/core/models/config.ts +22 -0
- package/src/core/models/document_type.ts +2 -2
- package/src/core/models/global_privacy_control.ts +45 -0
- package/src/core/models/network_config.ts +2 -2
- package/src/data/api/__tests__/smile_id_api.test.ts +275 -1
- package/src/data/api/interceptors/__tests__/credential_header_redaction.test.ts +144 -0
- package/src/data/api/interceptors/__tests__/gzip_interceptor.test.ts +83 -0
- package/src/data/api/interceptors/smile_auth_interceptor.ts +3 -18
- package/src/data/api/smile_id_api.ts +36 -49
- package/src/data/compression/__tests__/payload_compressor_real_jpeg.test.ts +6 -2
- package/src/data/dsl/__tests__/use_smile_id_network_builder.test.ts +157 -0
- package/src/data/dsl/builder/__tests__/config_builders.test.ts +62 -0
- package/src/data/dsl/builder/retry_config_builder.ts +6 -6
- package/src/data/factory/__tests__/retry_gzip_mac_composition.test.ts +163 -0
- package/src/data/factory/__tests__/signed_job_submission_headers.test.ts +1 -1
- package/src/data/model/__tests__/token_payload.test.ts +224 -0
- package/src/data/model/__tests__/user_details_payload.test.ts +100 -0
- package/src/data/model/job_request.ts +27 -12
- package/src/data/model/token_payload.ts +182 -0
- package/src/data/model/user_details_payload.ts +84 -0
- package/src/data/repository/__tests__/network_retries.test.ts +1 -1
- package/src/data/repository/__tests__/repository_dispatch.test.ts +366 -0
- package/src/data/repository/__tests__/use_smile_id_repository.test.ts +1 -1
- package/src/data/security/__tests__/request_canonicalizer.test.ts +132 -0
- package/src/data/security/__tests__/signing_crypto.test.ts +203 -0
- package/src/data/smile_id_urls.ts +1 -1
- package/src/data/util/__tests__/retry_util.test.ts +25 -0
- package/src/data/util/__tests__/use_smile_id_token_decoder.test.ts +179 -0
- package/src/data/util/retry_util.ts +9 -1
- package/src/data/util/use_smile_id_token_decoder.ts +29 -8
- package/src/index.ts +6 -4
- package/src/l10n/__tests__/use_smile_id_localizations.test.ts +122 -5
- package/src/l10n/__tests__/use_smile_id_localizations_provider.test.tsx +112 -0
- package/src/l10n/__tests__/use_smile_id_localizations_surface.test.ts +231 -0
- package/src/l10n/strings_en.ts +5 -1
- package/src/l10n/use_smile_id_localizations.ts +80 -3
- package/src/metadata/__tests__/device_orientation_sampling.test.ts +165 -0
- package/src/metadata/__tests__/geolocation.test.ts +150 -0
- package/src/metadata/__tests__/metadata_configuration_mappers.test.ts +39 -0
- package/src/metadata/__tests__/metadata_configuration_objects.test.ts +2 -1
- package/src/metadata/__tests__/metadata_device_context.test.ts +3 -3
- package/src/metadata/__tests__/metadata_device_os_android.test.ts +18 -0
- package/src/metadata/__tests__/metadata_golden_fixture.json +1 -1
- package/src/metadata/__tests__/metadata_payload_golden.test.ts +4 -4
- package/src/metadata/__tests__/optional_native_modules.test.ts +234 -0
- package/src/metadata/__tests__/use_smile_id_metadata.test.ts +1 -1
- package/src/metadata/__tests__/use_smile_id_metadata_factory.test.ts +615 -0
- package/src/metadata/builder_configuration.ts +6 -0
- package/src/metadata/metadata_configuration_mappers.ts +21 -7
- package/src/metadata/use_smile_id_metadata_factory.ts +17 -6
- package/src/presentation/assets/si_document_green_book_hero_animation.json +1 -4668
- package/src/presentation/assets/si_document_hero_animation.json +1 -4799
- package/src/presentation/assets/si_document_hero_back_animation.json +1 -2039
- package/src/presentation/assets/si_document_passport_hero_animation.json +1 -14491
- package/src/presentation/assets/si_ess_all_directions_hero_animation.json +1 -0
- package/src/presentation/assets/si_ess_animation_all_directions.json +1 -6589
- package/src/presentation/assets/si_selfie_hero_animation.json +1 -1439
- package/src/presentation/assets/si_smile_to_capture_animation.json +1 -1439
- package/src/presentation/components/__tests__/use_smile_id_content_card.test.tsx +112 -0
- package/src/presentation/components/__tests__/use_smile_id_enhanced_smart_selfie_clip.test.tsx +9 -4
- package/src/presentation/components/__tests__/use_smile_id_face_oval_image.test.tsx +190 -0
- package/src/presentation/components/__tests__/use_smile_id_instructions_hero.test.tsx +44 -0
- package/src/presentation/components/__tests__/use_smile_id_learn_more_content.test.tsx +159 -0
- package/src/presentation/components/__tests__/use_smile_id_processing_center_indicator.test.tsx +88 -0
- package/src/presentation/components/use_smile_id_button.tsx +7 -2
- package/src/presentation/components/use_smile_id_enhanced_smart_selfie_clip.tsx +9 -3
- package/src/presentation/components/use_smile_id_instructions_hero.tsx +10 -0
- package/src/presentation/flow/__tests__/document_flow_navigation.test.ts +3 -3
- package/src/presentation/flow/__tests__/flow_navigation_manager.test.ts +372 -1
- package/src/presentation/flow/__tests__/use_smile_id_flow.test.tsx +651 -0
- package/src/presentation/flow/dsl/__tests__/use_smile_id_builder_component.test.tsx +120 -0
- package/src/presentation/flow/dsl/builder/__tests__/config_builder.test.ts +25 -0
- package/src/presentation/flow/dsl/builder/config_builder.ts +21 -0
- package/src/presentation/flow/dsl/builder/screens_builder.ts +7 -12
- package/src/presentation/flow/dsl/use_smile_id_flow_builder.ts +27 -1
- package/src/presentation/flow/flow_navigation_manager.ts +108 -93
- package/src/presentation/flow/graph/__tests__/screen_renderer.test.tsx +102 -0
- package/src/presentation/flow/model/instructions_defaults.ts +1 -1
- package/src/presentation/flow/screen/__tests__/orchestrated_capture_screen.test.tsx +836 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_consent_screen.test.tsx +165 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_instructions_screen.test.tsx +163 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_preview_screen.test.tsx +224 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_processing_screen.test.tsx +338 -0
- package/src/presentation/flow/screen/orchestrated_capture_screen.tsx +18 -3
- package/src/presentation/flow/screen/orchestrated_consent_screen.tsx +5 -0
- package/src/presentation/flow/screen/orchestrated_preview_screen.tsx +0 -12
- package/src/presentation/flow/screen/orchestrated_processing_screen.tsx +42 -5
- package/src/presentation/flow/use_smile_id_flow.tsx +63 -12
- package/src/presentation/flow/validation/__tests__/flow_validator.test.ts +219 -1
- package/src/presentation/flow/validation/__tests__/job_type_validator.test.ts +200 -0
- package/src/presentation/flow/validation/flow_validator.ts +85 -57
- package/src/presentation/flow/validation/job_type_validator.ts +73 -39
- package/src/presentation/flow/validation/user_details_validator.ts +53 -0
- package/src/presentation/screen/__tests__/capture_ui_state.test.ts +66 -47
- package/src/presentation/screen/__tests__/ess_turn_haptics.test.ts +15 -11
- package/src/presentation/screen/__tests__/feedback_copy_table.test.ts +145 -0
- package/src/presentation/screen/__tests__/scan_state_to_overlay_state.test.ts +47 -27
- package/src/presentation/screen/__tests__/use_smile_id_capture_screen.test.tsx +524 -14
- package/src/presentation/screen/__tests__/use_smile_id_document_back_instructions.test.tsx +4 -2
- package/src/presentation/screen/__tests__/use_smile_id_permission_screen.test.tsx +68 -0
- package/src/presentation/screen/__tests__/use_smile_id_preview_screen.test.tsx +10 -40
- package/src/presentation/screen/helpers/__tests__/use_capture_orientation_lock.test.tsx +212 -0
- package/src/presentation/screen/helpers/capture_screen_helpers.ts +1 -0
- package/src/presentation/screen/helpers/capture_ui_state.ts +27 -27
- package/src/presentation/screen/helpers/ess_turn_haptics.ts +9 -9
- package/src/presentation/screen/helpers/scan_state_to_overlay_state.ts +13 -13
- package/src/presentation/screen/helpers/use_capture_orientation_lock.ts +69 -7
- package/src/presentation/screen/use_smile_id_capture_screen.tsx +107 -28
- package/src/presentation/screen/use_smile_id_consent_screen.tsx +16 -5
- package/src/presentation/screen/use_smile_id_document_back_instructions.tsx +14 -23
- package/src/presentation/screen/use_smile_id_document_preview_screen.tsx +1 -1
- package/src/presentation/screen/use_smile_id_preview_screen.tsx +13 -45
- package/src/presentation/screen/use_smile_id_processing_screen.tsx +1 -1
- package/src/presentation/theme/__tests__/use_use_smile_id_fonts.test.tsx +166 -0
- package/src/presentation/utils/__tests__/locale_utils.test.ts +46 -5
- package/src/presentation/utils/locale_utils.ts +13 -4
- package/src/testing/__tests__/fake_face_analyzer.test.ts +42 -0
- package/src/testing/__tests__/scenario_expectations.test.ts +110 -0
- package/src/testing/__tests__/scenario_loader.test.ts +64 -0
- package/src/testing/fake_face_analyzer.ts +82 -0
- package/src/testing/index.ts +15 -0
- package/src/testing/scenario_expectations.ts +87 -0
- package/src/testing/scenario_loader.ts +83 -0
- package/src/testing/scripted_scan_results.ts +66 -0
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.d.ts +0 -15
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.d.ts.map +0 -1
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.js +0 -19
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.js.map +0 -1
- package/src/presentation/components/use_smile_id_face_silhouette_overlay.tsx +0 -27
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { create as createRenderer, act } from "react-test-renderer";
|
|
4
|
+
|
|
5
|
+
// `vi.mock` is hoisted above the imports, so anything its factory closes over
|
|
6
|
+
// must be created with `vi.hoisted` or it is still in the TDZ when the factory
|
|
7
|
+
// runs.
|
|
8
|
+
const { invalidProps, successProps } = vi.hoisted(() => ({
|
|
9
|
+
invalidProps: { current: undefined as Record<string, unknown> | undefined },
|
|
10
|
+
successProps: { current: undefined as Record<string, unknown> | undefined },
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
// Stand in for the two flow renderers so these tests exercise the
|
|
14
|
+
// build-and-dispatch decision the component owns, not the screen runtime
|
|
15
|
+
// (which has its own suites).
|
|
16
|
+
vi.mock("../../use_smile_id_flow", () => ({
|
|
17
|
+
FlowInvalidDispatcher: (props: Record<string, unknown>) => {
|
|
18
|
+
invalidProps.current = props;
|
|
19
|
+
return null;
|
|
20
|
+
},
|
|
21
|
+
FlowSuccessRenderer: (props: Record<string, unknown>) => {
|
|
22
|
+
successProps.current = props;
|
|
23
|
+
return null;
|
|
24
|
+
},
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
import { UseSmileIDBuilder } from "../use_smile_id_builder";
|
|
28
|
+
import type { UseSmileIDFlowBuilder } from "../use_smile_id_flow_builder";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* `<UseSmileIDBuilder>` runs the partner's closure exactly once per mount,
|
|
32
|
+
* builds the flow, and routes the outcome: a valid configuration renders the
|
|
33
|
+
* flow, an invalid one hands the partner's `onResult` and debug-mode flag to
|
|
34
|
+
* the invalid dispatcher. Re-running the closure on every render would
|
|
35
|
+
* restart a partner's flow mid-capture.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
function render(element: React.ReactElement) {
|
|
39
|
+
let tree!: ReturnType<typeof createRenderer>;
|
|
40
|
+
act(() => {
|
|
41
|
+
tree = createRenderer(element);
|
|
42
|
+
});
|
|
43
|
+
return tree;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function validFlow(builder: UseSmileIDFlowBuilder): void {
|
|
47
|
+
builder.screens((screens) => {
|
|
48
|
+
screens.instructions();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
describe("UseSmileIDBuilder", () => {
|
|
53
|
+
beforeEach(() => {
|
|
54
|
+
invalidProps.current = undefined;
|
|
55
|
+
successProps.current = undefined;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("renders the flow when the configuration builds", () => {
|
|
59
|
+
render(<UseSmileIDBuilder builder={validFlow} />);
|
|
60
|
+
|
|
61
|
+
expect(invalidProps.current).toBeUndefined();
|
|
62
|
+
expect(successProps.current).toBeDefined();
|
|
63
|
+
const configuration = successProps.current?.configuration as {
|
|
64
|
+
screens: { steps: readonly unknown[] };
|
|
65
|
+
};
|
|
66
|
+
expect(configuration.screens.steps).toHaveLength(1);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("routes an invalid configuration to the dispatcher with the partner callback", () => {
|
|
70
|
+
const onResult = vi.fn();
|
|
71
|
+
render(
|
|
72
|
+
<UseSmileIDBuilder
|
|
73
|
+
builder={(builder) => {
|
|
74
|
+
builder.onResult = onResult;
|
|
75
|
+
}}
|
|
76
|
+
/>,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
expect(successProps.current).toBeUndefined();
|
|
80
|
+
expect(invalidProps.current?.onResult).toBe(onResult);
|
|
81
|
+
expect(invalidProps.current?.enableDebugMode).toBe(false);
|
|
82
|
+
const result = invalidProps.current?.result as { kind: string };
|
|
83
|
+
expect(result.kind).toBe("invalid");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("forwards the partner's debug-mode opt-in to the dispatcher", () => {
|
|
87
|
+
render(
|
|
88
|
+
<UseSmileIDBuilder
|
|
89
|
+
builder={(builder) => {
|
|
90
|
+
builder.config((config) => {
|
|
91
|
+
config.enableDebugMode = true;
|
|
92
|
+
});
|
|
93
|
+
}}
|
|
94
|
+
/>,
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
expect(invalidProps.current?.enableDebugMode).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("reports debug mode as off when the config block is never opened", () => {
|
|
101
|
+
render(<UseSmileIDBuilder builder={() => {}} />);
|
|
102
|
+
|
|
103
|
+
expect(invalidProps.current?.enableDebugMode).toBe(false);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("runs the builder closure once per mount, not per render", () => {
|
|
107
|
+
const builder = vi.fn(validFlow);
|
|
108
|
+
const tree = render(<UseSmileIDBuilder builder={builder} />);
|
|
109
|
+
|
|
110
|
+
act(() => {
|
|
111
|
+
tree.update(<UseSmileIDBuilder builder={builder} />);
|
|
112
|
+
});
|
|
113
|
+
act(() => {
|
|
114
|
+
tree.update(<UseSmileIDBuilder builder={vi.fn(validFlow)} />);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
expect(builder).toHaveBeenCalledTimes(1);
|
|
118
|
+
expect(successProps.current).toBeDefined();
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import * as ScreenOrientation from "expo-screen-orientation";
|
|
3
|
+
import { GlobalPrivacyControl } from "../../../../../core/models/global_privacy_control";
|
|
4
|
+
import { UseSmileIDConfigBuilder } from "../config_builder";
|
|
5
|
+
|
|
6
|
+
describe("UseSmileIDConfigBuilder", () => {
|
|
7
|
+
it("snapshots the documented defaults", () => {
|
|
8
|
+
expect(new UseSmileIDConfigBuilder().build()).toEqual({
|
|
9
|
+
enableCrashReporting: true,
|
|
10
|
+
enableDebugMode: false,
|
|
11
|
+
allowOfflineMode: false,
|
|
12
|
+
globalPrivacyControl: GlobalPrivacyControl.OptOut,
|
|
13
|
+
exitOrientations: ScreenOrientation.OrientationLock.PORTRAIT_UP,
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("carries an overridden exit orientation lock into the snapshot", () => {
|
|
18
|
+
const builder = new UseSmileIDConfigBuilder();
|
|
19
|
+
builder.exitOrientations = ScreenOrientation.OrientationLock.DEFAULT;
|
|
20
|
+
|
|
21
|
+
expect(builder.build().exitOrientations).toBe(
|
|
22
|
+
ScreenOrientation.OrientationLock.DEFAULT,
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import * as ScreenOrientation from "expo-screen-orientation";
|
|
1
2
|
import type { ConfigOptions } from "../../../../core/models/config";
|
|
3
|
+
import { GlobalPrivacyControl } from "../../../../core/models/global_privacy_control";
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* `b.config((c) => { c.enableCrashReporting = false; ... })`
|
|
@@ -26,11 +28,30 @@ export class UseSmileIDConfigBuilder {
|
|
|
26
28
|
*/
|
|
27
29
|
allowOfflineMode = false;
|
|
28
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Consent posture for every session (`global_privacy_control`). Defaults
|
|
33
|
+
* to `GlobalPrivacyControl.OptOut` — the opt-out consent layout is
|
|
34
|
+
* enforced universally and regional detection is ignored. Set
|
|
35
|
+
* `GlobalPrivacyControl.OptIn` to keep the legacy regional mechanics
|
|
36
|
+
* (opt-in inside the EU, opt-out elsewhere).
|
|
37
|
+
*/
|
|
38
|
+
globalPrivacyControl: GlobalPrivacyControl = GlobalPrivacyControl.OptOut;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Orientation lock applied when a capture screen leaves the screen.
|
|
42
|
+
* Defaults to portrait-up; set `ScreenOrientation.OrientationLock.DEFAULT`
|
|
43
|
+
* if your app supports more than one orientation.
|
|
44
|
+
*/
|
|
45
|
+
exitOrientations: ScreenOrientation.OrientationLock =
|
|
46
|
+
ScreenOrientation.OrientationLock.PORTRAIT_UP;
|
|
47
|
+
|
|
29
48
|
build(): ConfigOptions {
|
|
30
49
|
return Object.freeze({
|
|
31
50
|
enableCrashReporting: this.enableCrashReporting,
|
|
32
51
|
enableDebugMode: this.enableDebugMode,
|
|
33
52
|
allowOfflineMode: this.allowOfflineMode,
|
|
53
|
+
globalPrivacyControl: this.globalPrivacyControl,
|
|
54
|
+
exitOrientations: this.exitOrientations,
|
|
34
55
|
});
|
|
35
56
|
}
|
|
36
57
|
}
|
|
@@ -29,15 +29,13 @@ export type ButtonSlot = (props: {
|
|
|
29
29
|
|
|
30
30
|
// --- Per-screen builders ---------------------------------------------------
|
|
31
31
|
|
|
32
|
+
// Required fields stay optional on the type because partners assign them by mutating this builder; the flow validator rejects a missing one.
|
|
32
33
|
export class ConsentConfigBuilder {
|
|
33
|
-
/** Your company name, shown in the consent copy. */
|
|
34
|
+
/** Required. Your company name, shown in the consent copy. */
|
|
34
35
|
partnerName = "";
|
|
35
|
-
/**
|
|
36
|
-
* Optional partner logo shown on the consent screen, rendered next to
|
|
37
|
-
* the Smile ID icon at the top.
|
|
38
|
-
*/
|
|
36
|
+
/** Required. Your logo, shown on the consent screen next to the Smile ID icon. */
|
|
39
37
|
partnerIcon?: ReactNode;
|
|
40
|
-
/** URL of your privacy policy, linked from the consent screen. */
|
|
38
|
+
/** Required. URL of your privacy policy, linked from the consent screen. */
|
|
41
39
|
partnerPrivacyPolicyUrl?: string;
|
|
42
40
|
/**
|
|
43
41
|
* Whether to show the "Powered by Smile ID" attribution. Defaults to
|
|
@@ -89,8 +87,9 @@ export class InstructionsConfigBuilder {
|
|
|
89
87
|
|
|
90
88
|
export class SelfieCaptureConfigBuilder {
|
|
91
89
|
/**
|
|
92
|
-
* When true,
|
|
93
|
-
* the subject.
|
|
90
|
+
* When true, the whole selfie session captures on the rear camera so an
|
|
91
|
+
* assisting agent can point it at the subject. Cannot be combined with
|
|
92
|
+
* {@link enableEnhancedLiveness}.
|
|
94
93
|
*/
|
|
95
94
|
allowAgentMode = false;
|
|
96
95
|
/**
|
|
@@ -180,10 +179,6 @@ export class PreviewConfigBuilder {
|
|
|
180
179
|
* true.
|
|
181
180
|
*/
|
|
182
181
|
showAttribution = true;
|
|
183
|
-
/** Provides a custom continue button in place of the default. */
|
|
184
|
-
continueButton?: ButtonSlot;
|
|
185
|
-
/** Provides a custom cancel button in place of the default. */
|
|
186
|
-
cancelButton?: ButtonSlot;
|
|
187
182
|
}
|
|
188
183
|
|
|
189
184
|
export class ProcessingConfigBuilder {
|
|
@@ -33,6 +33,8 @@ import {
|
|
|
33
33
|
} from "../validation/flow_validator";
|
|
34
34
|
import { ValidationState } from "../validation/validation_state";
|
|
35
35
|
import type { FlowBuildResult } from "./flow_build_result";
|
|
36
|
+
import { decodeSmileIDToken } from "../../../data/util/use_smile_id_token_decoder";
|
|
37
|
+
import type { TokenPayload } from "../../../data/model/token_payload";
|
|
36
38
|
|
|
37
39
|
/**
|
|
38
40
|
* Top-level DSL builder.
|
|
@@ -326,6 +328,13 @@ export class UseSmileIDFlowBuilder {
|
|
|
326
328
|
const screens = this._screens?.build();
|
|
327
329
|
const network = this._network?.build();
|
|
328
330
|
const mlConfig = this._ml?.build();
|
|
331
|
+
const config = this._config?.build();
|
|
332
|
+
|
|
333
|
+
// Decode the JWT `payload` claim (pure, synchronous) so validation
|
|
334
|
+
// can relax the userDetails/consent requirements the token already
|
|
335
|
+
// covers. Skip rules mirror FlowNavigationManager's decode: offline
|
|
336
|
+
// mode and a missing/blank token keep the strict legacy rules.
|
|
337
|
+
const tokenPayload = decodeTokenPayload(config?.allowOfflineMode, network);
|
|
329
338
|
|
|
330
339
|
const issues = runFlowValidation({
|
|
331
340
|
steps: screens?.steps ?? [],
|
|
@@ -338,6 +347,7 @@ export class UseSmileIDFlowBuilder {
|
|
|
338
347
|
enhancedDocumentVerificationParams:
|
|
339
348
|
this.enhancedDocumentVerificationParams,
|
|
340
349
|
userDetails: this.userDetails,
|
|
350
|
+
tokenPayload,
|
|
341
351
|
});
|
|
342
352
|
const state = ValidationState.invalid(issues);
|
|
343
353
|
const blocking = firstErrorIssue(state);
|
|
@@ -386,7 +396,7 @@ export class UseSmileIDFlowBuilder {
|
|
|
386
396
|
: {}),
|
|
387
397
|
...(this.userDetails ? { userDetails: this.userDetails } : {}),
|
|
388
398
|
...(this.userId ? { userId: this.userId } : {}),
|
|
389
|
-
...(
|
|
399
|
+
...(config ? { config } : {}),
|
|
390
400
|
...(this._theme ? { theme: this._theme.build() } : {}),
|
|
391
401
|
...(network ? { network } : {}),
|
|
392
402
|
...(mlConfig ? { ml: mlConfig } : {}),
|
|
@@ -402,6 +412,22 @@ export class UseSmileIDFlowBuilder {
|
|
|
402
412
|
}
|
|
403
413
|
}
|
|
404
414
|
|
|
415
|
+
/**
|
|
416
|
+
* Decode the `payload` claim from the partner JWT for build-time
|
|
417
|
+
* validation. `undefined` for offline mode, no/blank token, or an
|
|
418
|
+
* unparseable token — every validation rule then stays exactly as
|
|
419
|
+
* strict as before token support existed.
|
|
420
|
+
*/
|
|
421
|
+
function decodeTokenPayload(
|
|
422
|
+
allowOfflineMode: boolean | undefined,
|
|
423
|
+
network: NetworkConfig | undefined,
|
|
424
|
+
): TokenPayload | undefined {
|
|
425
|
+
if (allowOfflineMode) return undefined;
|
|
426
|
+
const token = network?.config?.token;
|
|
427
|
+
if (!token || token.length === 0) return undefined;
|
|
428
|
+
return decodeSmileIDToken(token)?.tokenPayload;
|
|
429
|
+
}
|
|
430
|
+
|
|
405
431
|
/**
|
|
406
432
|
* Frozen snapshot produced by `UseSmileIDFlowBuilder.build()`.
|
|
407
433
|
*
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import type { ScreenSpec } from "./dsl/builder/screens_builder";
|
|
2
2
|
import type { FlowConfigurationSnapshot } from "./dsl/use_smile_id_flow_builder";
|
|
3
3
|
import type { JobSubmissionState } from "./job_submission_state";
|
|
4
|
-
import type {
|
|
5
|
-
DocumentVerificationRequest,
|
|
6
|
-
EnhancedDocumentVerificationRequest,
|
|
7
|
-
JobRequest,
|
|
8
|
-
} from "../../data/model/job_request";
|
|
4
|
+
import type { JobRequest } from "../../data/model/job_request";
|
|
9
5
|
import type { UseSmileIDRepository } from "../../data/repository/use_smile_id_repository";
|
|
10
|
-
import type {
|
|
11
|
-
ConsentInformation,
|
|
12
|
-
DocumentVerificationParams,
|
|
13
|
-
EnhancedDocumentVerificationParams,
|
|
14
|
-
UserDetails,
|
|
15
|
-
} from "../../core/models/params";
|
|
6
|
+
import type { ConsentInformation, UserDetails } from "../../core/models/params";
|
|
16
7
|
import { JobType } from "../../core/models/job_type";
|
|
17
8
|
import { CaptureType } from "../../core/models/ml_config";
|
|
18
9
|
import {
|
|
@@ -20,17 +11,17 @@ import {
|
|
|
20
11
|
type DocumentType,
|
|
21
12
|
} from "../../core/models/document_type";
|
|
22
13
|
import type { JobSubmissionResponse } from "../../data/model/job_submission_response";
|
|
23
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
MissingJobTypeException,
|
|
16
|
+
MissingRequiredFieldException,
|
|
17
|
+
} from "../../core/exception/job_validation_exceptions";
|
|
24
18
|
import {
|
|
25
19
|
UseSmileIDAnalyticsEventTypes,
|
|
26
20
|
UseSmileIDAnalyticsParamKeys,
|
|
27
21
|
UseSmileIDAnalyticsScreenNames,
|
|
28
22
|
type UseSmileIDAnalyticsEventType,
|
|
29
23
|
} from "./analytics/use_smile_id_analytics_event";
|
|
30
|
-
import type {
|
|
31
|
-
MetadataEntry,
|
|
32
|
-
UseSmileIDMetadata,
|
|
33
|
-
} from "../../metadata/use_smile_id_metadata";
|
|
24
|
+
import type { MetadataEntry } from "../../metadata/use_smile_id_metadata";
|
|
34
25
|
import {
|
|
35
26
|
UseSmileIDMetadataFactory,
|
|
36
27
|
type MetadataProvider,
|
|
@@ -52,6 +43,16 @@ import {
|
|
|
52
43
|
decodeSmileIDToken,
|
|
53
44
|
type DecodedToken,
|
|
54
45
|
} from "../../data/util/use_smile_id_token_decoder";
|
|
46
|
+
import {
|
|
47
|
+
isTokenConsentComplete,
|
|
48
|
+
bindsRequiredUserDetails,
|
|
49
|
+
type TokenPayload,
|
|
50
|
+
} from "../../data/model/token_payload";
|
|
51
|
+
import {
|
|
52
|
+
isUserDetailsPayloadEmpty,
|
|
53
|
+
userDetailsPayloadFrom,
|
|
54
|
+
} from "../../data/model/user_details_payload";
|
|
55
|
+
import type { UserDetailsPayload } from "../../data/model/user_details_payload";
|
|
55
56
|
import {
|
|
56
57
|
DocumentSide,
|
|
57
58
|
EnhancedSmartSelfieConfig,
|
|
@@ -166,6 +167,15 @@ export class FlowNavigationManager {
|
|
|
166
167
|
/** Canonical `partner_id` decoded from the JWT (raw); resolved via the [partnerId] getter. */
|
|
167
168
|
private readonly _resolvedPartnerId: string | undefined;
|
|
168
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Token-bound user-detail/consent bindings decoded from the JWT
|
|
172
|
+
* `payload` claim, resolved once at construction alongside
|
|
173
|
+
* `resolvedSdkConfig`. `undefined` for offline mode / no token /
|
|
174
|
+
* legacy token — assembly then requires and sends everything exactly
|
|
175
|
+
* as before token support existed.
|
|
176
|
+
*/
|
|
177
|
+
private readonly _resolvedTokenPayload: TokenPayload | undefined;
|
|
178
|
+
|
|
169
179
|
/**
|
|
170
180
|
* Partner identifier the capture screen stamps into the Smile EXIF tag — the tag's HMAC/AES
|
|
171
181
|
* keys derive from it and the backend validates the tag against the request's partner_id.
|
|
@@ -188,7 +198,6 @@ export class FlowNavigationManager {
|
|
|
188
198
|
|
|
189
199
|
constructor(options: FlowNavigationManagerOptions) {
|
|
190
200
|
this._configuration = options.configuration;
|
|
191
|
-
this._steps = options.configuration.screens.steps;
|
|
192
201
|
this._onExit = options.onExit;
|
|
193
202
|
this._repository = options.repository;
|
|
194
203
|
// Fall back to a fresh factory so capture-only harnesses still build
|
|
@@ -202,6 +211,14 @@ export class FlowNavigationManager {
|
|
|
202
211
|
);
|
|
203
212
|
this.resolvedSdkConfig = decodedToken?.sdkConfig;
|
|
204
213
|
this._resolvedPartnerId = decodedToken?.partnerId;
|
|
214
|
+
this._resolvedTokenPayload = decodedToken?.tokenPayload;
|
|
215
|
+
// Token consent always wins: a complete binding drops the consent
|
|
216
|
+
// screen from the flow — the server injects the token's record, so
|
|
217
|
+
// nothing is collected here.
|
|
218
|
+
const steps = options.configuration.screens.steps;
|
|
219
|
+
this._steps = isTokenConsentComplete(decodedToken?.tokenPayload?.consent)
|
|
220
|
+
? steps.filter((s) => s.kind !== "consent")
|
|
221
|
+
: steps;
|
|
205
222
|
// Seed the path with the first screen so currentScreen/renderer have a
|
|
206
223
|
// deterministic start. Empty path → host renders the "no screens"
|
|
207
224
|
// sentinel (validation rejects empty screens at build time anyway).
|
|
@@ -693,9 +710,14 @@ export class FlowNavigationManager {
|
|
|
693
710
|
void this._submit();
|
|
694
711
|
}
|
|
695
712
|
|
|
696
|
-
/**
|
|
713
|
+
/**
|
|
714
|
+
* Reset to `notAttempted` and re-fire submission (processing screen's
|
|
715
|
+
* onRetry). Ignored while a submission is in flight — resetting then would
|
|
716
|
+
* defeat `beginSubmissionIfNeeded()`'s single-flight guard.
|
|
717
|
+
*/
|
|
697
718
|
retrySubmission(): void {
|
|
698
719
|
if (this._disposed) return;
|
|
720
|
+
if (this._jobSubmissionState.kind === "loading") return;
|
|
699
721
|
this._setSubmissionState({ kind: "notAttempted" });
|
|
700
722
|
this.beginSubmissionIfNeeded();
|
|
701
723
|
}
|
|
@@ -770,10 +792,18 @@ export class FlowNavigationManager {
|
|
|
770
792
|
private _assembleJob(): JobRequest {
|
|
771
793
|
const config = this._configuration;
|
|
772
794
|
const jobType = config.network?.config?.jobType ?? JobType.unknown;
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
795
|
+
// Token consent always wins: the `consent` part is omitted — the
|
|
796
|
+
// server injects the token's record — and any local preset or
|
|
797
|
+
// capture is ignored. Without a token binding, a local source
|
|
798
|
+
// (captured on the consent screen, else the builder preset) is
|
|
799
|
+
// sent in full, and the legacy DEFAULT_CONSENT placeholder covers
|
|
800
|
+
// the no-source case.
|
|
801
|
+
const consent = isTokenConsentComplete(this._resolvedTokenPayload?.consent)
|
|
802
|
+
? undefined
|
|
803
|
+
: (this._captured.consentInformation ??
|
|
804
|
+
config.consentInformation ??
|
|
805
|
+
DEFAULT_CONSENT);
|
|
806
|
+
const consentField = consent !== undefined ? { consent } : {};
|
|
777
807
|
// Build the per-submission metadata snapshot so it travels on the
|
|
778
808
|
// request (API layer serializes `request.metadata` directly).
|
|
779
809
|
// Dynamic fields (orientation, locale, timezone) re-resolve per
|
|
@@ -801,8 +831,8 @@ export class FlowNavigationManager {
|
|
|
801
831
|
jobType: JobType.smartSelfieEnrollment,
|
|
802
832
|
selfieImage: selfie.selfiePath,
|
|
803
833
|
livenessImages: selfie.livenessPaths,
|
|
804
|
-
userDetails,
|
|
805
|
-
|
|
834
|
+
...(userDetails !== undefined ? { userDetails } : {}),
|
|
835
|
+
...consentField,
|
|
806
836
|
metadata,
|
|
807
837
|
enhanced: false,
|
|
808
838
|
expectedLivenessImageCount: this._expectedLivenessImageCount(),
|
|
@@ -817,9 +847,9 @@ export class FlowNavigationManager {
|
|
|
817
847
|
jobType: JobType.smartSelfieAuthentication,
|
|
818
848
|
selfieImage: selfie.selfiePath,
|
|
819
849
|
livenessImages: selfie.livenessPaths,
|
|
820
|
-
userDetails,
|
|
850
|
+
...(userDetails !== undefined ? { userDetails } : {}),
|
|
821
851
|
userId,
|
|
822
|
-
|
|
852
|
+
...consentField,
|
|
823
853
|
metadata,
|
|
824
854
|
enhanced: false,
|
|
825
855
|
expectedLivenessImageCount: this._expectedLivenessImageCount(),
|
|
@@ -840,8 +870,8 @@ export class FlowNavigationManager {
|
|
|
840
870
|
selfieImage: selfie.selfiePath,
|
|
841
871
|
livenessImages: selfie.livenessPaths,
|
|
842
872
|
params,
|
|
843
|
-
userDetails,
|
|
844
|
-
|
|
873
|
+
...(userDetails !== undefined ? { userDetails } : {}),
|
|
874
|
+
...consentField,
|
|
845
875
|
metadata,
|
|
846
876
|
expectedLivenessImageCount: this._expectedLivenessImageCount(),
|
|
847
877
|
};
|
|
@@ -857,14 +887,17 @@ export class FlowNavigationManager {
|
|
|
857
887
|
});
|
|
858
888
|
}
|
|
859
889
|
const userDetails = this._requireUserDetails(config);
|
|
860
|
-
return
|
|
861
|
-
|
|
862
|
-
front,
|
|
863
|
-
params,
|
|
864
|
-
|
|
865
|
-
|
|
890
|
+
return {
|
|
891
|
+
jobType: JobType.documentVerification,
|
|
892
|
+
...this._documentRequestFields(selfie, front),
|
|
893
|
+
country: params.country,
|
|
894
|
+
// Optional — omit when unset so the server classifies the document.
|
|
895
|
+
...(params.idType ? { idType: params.idType } : {}),
|
|
896
|
+
...(userDetails !== undefined ? { userDetails } : {}),
|
|
897
|
+
...consentField,
|
|
866
898
|
metadata,
|
|
867
|
-
|
|
899
|
+
expectedLivenessImageCount: this._expectedLivenessImageCount(),
|
|
900
|
+
};
|
|
868
901
|
}
|
|
869
902
|
|
|
870
903
|
case JobType.enhancedDocumentVerification: {
|
|
@@ -877,14 +910,16 @@ export class FlowNavigationManager {
|
|
|
877
910
|
});
|
|
878
911
|
}
|
|
879
912
|
const userDetails = this._requireUserDetails(config);
|
|
880
|
-
return
|
|
881
|
-
|
|
882
|
-
front,
|
|
883
|
-
params,
|
|
884
|
-
|
|
885
|
-
|
|
913
|
+
return {
|
|
914
|
+
jobType: JobType.enhancedDocumentVerification,
|
|
915
|
+
...this._documentRequestFields(selfie, front),
|
|
916
|
+
country: params.country,
|
|
917
|
+
idType: params.idType,
|
|
918
|
+
...(userDetails !== undefined ? { userDetails } : {}),
|
|
919
|
+
...consentField,
|
|
886
920
|
metadata,
|
|
887
|
-
|
|
921
|
+
expectedLivenessImageCount: this._expectedLivenessImageCount(),
|
|
922
|
+
};
|
|
888
923
|
}
|
|
889
924
|
|
|
890
925
|
case JobType.enhancedKyc: {
|
|
@@ -898,8 +933,8 @@ export class FlowNavigationManager {
|
|
|
898
933
|
return {
|
|
899
934
|
jobType: JobType.enhancedKyc,
|
|
900
935
|
params,
|
|
901
|
-
userDetails,
|
|
902
|
-
|
|
936
|
+
...(userDetails !== undefined ? { userDetails } : {}),
|
|
937
|
+
...consentField,
|
|
903
938
|
metadata,
|
|
904
939
|
};
|
|
905
940
|
}
|
|
@@ -919,18 +954,15 @@ export class FlowNavigationManager {
|
|
|
919
954
|
return {
|
|
920
955
|
jobType: JobType.bvn,
|
|
921
956
|
params,
|
|
922
|
-
userDetails,
|
|
923
|
-
|
|
957
|
+
...(userDetails !== undefined ? { userDetails } : {}),
|
|
958
|
+
...consentField,
|
|
924
959
|
metadata,
|
|
925
960
|
};
|
|
926
961
|
}
|
|
927
962
|
|
|
928
963
|
case JobType.unknown:
|
|
929
964
|
default:
|
|
930
|
-
throw new
|
|
931
|
-
"Job type not configured — call `b.network((n) => n.config((c) => { c.jobType = JobType.<...>; }))` " +
|
|
932
|
-
"before mounting <UseSmileIDBuilder>.",
|
|
933
|
-
);
|
|
965
|
+
throw new MissingJobTypeException();
|
|
934
966
|
}
|
|
935
967
|
}
|
|
936
968
|
|
|
@@ -945,12 +977,28 @@ export class FlowNavigationManager {
|
|
|
945
977
|
return { selfiePath, livenessPaths };
|
|
946
978
|
}
|
|
947
979
|
|
|
948
|
-
|
|
980
|
+
/**
|
|
981
|
+
* Resolve `b.userDetails` for the wire. May legitimately return
|
|
982
|
+
* `undefined` when the token binds every required field
|
|
983
|
+
* (`given_names`, `last_name`, and a contact field) — the
|
|
984
|
+
* `user_details` part is then omitted and the server injects the
|
|
985
|
+
* token's values. Otherwise throws exactly as before token support.
|
|
986
|
+
*/
|
|
987
|
+
private _requireUserDetails(
|
|
988
|
+
config: FlowConfigurationSnapshot,
|
|
989
|
+
): UserDetailsPayload | undefined {
|
|
949
990
|
const userDetails = config.userDetails;
|
|
950
991
|
if (!userDetails) {
|
|
992
|
+
if (bindsRequiredUserDetails(this._resolvedTokenPayload)) {
|
|
993
|
+
return undefined;
|
|
994
|
+
}
|
|
951
995
|
throw new MissingRequiredFieldException({ fieldName: "userDetails" });
|
|
952
996
|
}
|
|
953
|
-
|
|
997
|
+
const payload = userDetailsPayloadFrom(
|
|
998
|
+
userDetails,
|
|
999
|
+
this._resolvedTokenPayload,
|
|
1000
|
+
);
|
|
1001
|
+
return isUserDetailsPayloadEmpty(payload) ? undefined : payload;
|
|
954
1002
|
}
|
|
955
1003
|
|
|
956
1004
|
/**
|
|
@@ -974,58 +1022,25 @@ export class FlowNavigationManager {
|
|
|
974
1022
|
return frontDocumentPath;
|
|
975
1023
|
}
|
|
976
1024
|
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
readonly selfiePath: string;
|
|
980
|
-
readonly livenessPaths: readonly string[];
|
|
981
|
-
},
|
|
982
|
-
frontDocument: string,
|
|
983
|
-
params: DocumentVerificationParams,
|
|
984
|
-
userDetails: UserDetails,
|
|
985
|
-
consent: ConsentInformation,
|
|
986
|
-
metadata: UseSmileIDMetadata,
|
|
987
|
-
): DocumentVerificationRequest {
|
|
988
|
-
const { backDocumentPath } = this._captured;
|
|
989
|
-
return {
|
|
990
|
-
jobType: JobType.documentVerification,
|
|
991
|
-
selfieImage: selfie.selfiePath,
|
|
992
|
-
livenessImages: selfie.livenessPaths,
|
|
993
|
-
frontDocument,
|
|
994
|
-
...(backDocumentPath ? { backDocument: backDocumentPath } : {}),
|
|
995
|
-
country: params.country,
|
|
996
|
-
// Optional — omit when unset so the server classifies the document.
|
|
997
|
-
...(params.idType ? { idType: params.idType } : {}),
|
|
998
|
-
userDetails,
|
|
999
|
-
consent,
|
|
1000
|
-
metadata,
|
|
1001
|
-
expectedLivenessImageCount: this._expectedLivenessImageCount(),
|
|
1002
|
-
};
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
private _buildEnhancedDocumentRequest(
|
|
1025
|
+
/** Capture-artifact fields shared by both document request variants. */
|
|
1026
|
+
private _documentRequestFields(
|
|
1006
1027
|
selfie: {
|
|
1007
1028
|
readonly selfiePath: string;
|
|
1008
1029
|
readonly livenessPaths: readonly string[];
|
|
1009
1030
|
},
|
|
1010
1031
|
frontDocument: string,
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1032
|
+
): {
|
|
1033
|
+
readonly selfieImage: string;
|
|
1034
|
+
readonly livenessImages: readonly string[];
|
|
1035
|
+
readonly frontDocument: string;
|
|
1036
|
+
readonly backDocument?: string;
|
|
1037
|
+
} {
|
|
1016
1038
|
const { backDocumentPath } = this._captured;
|
|
1017
1039
|
return {
|
|
1018
|
-
jobType: JobType.enhancedDocumentVerification,
|
|
1019
1040
|
selfieImage: selfie.selfiePath,
|
|
1020
1041
|
livenessImages: selfie.livenessPaths,
|
|
1021
1042
|
frontDocument,
|
|
1022
1043
|
...(backDocumentPath ? { backDocument: backDocumentPath } : {}),
|
|
1023
|
-
country: params.country,
|
|
1024
|
-
idType: params.idType,
|
|
1025
|
-
userDetails,
|
|
1026
|
-
consent,
|
|
1027
|
-
metadata,
|
|
1028
|
-
expectedLivenessImageCount: this._expectedLivenessImageCount(),
|
|
1029
1044
|
};
|
|
1030
1045
|
}
|
|
1031
1046
|
|