From 67fcdeb13c72286648a08240d315700c47e57f72 Mon Sep 17 00:00:00 2001 From: Lauren George Date: Wed, 6 Nov 2024 17:05:46 -0500 Subject: [PATCH 1/2] LG-13761: ProofingComponents to store real vendor used to verify document PII **Why** * Prior to this change, we always stored 'aamva' in a `User`'s `proofing_components.source_check` column regardless of whether a call to AAMVA was made or not. Accuracy is good and storing the actual "vendor_name" will align our analytics across our events. **How** * Instead of hard-coding `vendor_name` in `proofing_components.source_check`, we dig into the result object (as produced by the `ResultAdjudicator`) for the actual vendor_name. This value should always be present even though we don't have any validators for it. * Adds `:source_check_vendor` field to `Idv::Session` to capture the vendor name actually utilized to validate the state ID attributes. * Pulling `vendor_name` from the result object makes testing a little messier, cleaning up the various vendor names in our specs should be done in future work. For now, a new constant with the known `source_check` names has been added (`Idv::Constants::Vendors::SOURCE_CHECK`). * No new specs have been added as the functionality hasn't changed, but the relevant specs, including one end-to-end feature test, have been updated to check the vendor name is in the expected list or matches a placeholder value. changelog: Internal, Analytics, Store correct vendor name in ProofingComponents --- .../concerns/idv/verify_info_concern.rb | 24 +++++++++-- .../idv/in_person/verify_info_controller.rb | 1 + app/controllers/idv/verify_info_controller.rb | 1 + app/services/idv/proofing_components.rb | 3 +- app/services/idv/session.rb | 41 +++++++++++++++++++ .../resolution/plugins/aamva_plugin.rb | 2 +- lib/idp/constants.rb | 3 ++ .../idv/verify_info_controller_spec.rb | 17 +++++--- spec/features/idv/analytics_spec.rb | 29 +++++++------ spec/features/idv/end_to_end_idv_spec.rb | 4 +- spec/features/idv/proofing_components_spec.rb | 1 + spec/services/idv/proofing_components_spec.rb | 16 ++++++++ 12 files changed, 116 insertions(+), 26 deletions(-) diff --git a/app/controllers/concerns/idv/verify_info_concern.rb b/app/controllers/concerns/idv/verify_info_concern.rb index 297ac4a2a95..f3c0ac15f3a 100644 --- a/app/controllers/concerns/idv/verify_info_concern.rb +++ b/app/controllers/concerns/idv/verify_info_concern.rb @@ -232,6 +232,7 @@ def async_state_done(current_async_state) if form_response.success? save_threatmetrix_status(form_response) + save_source_check_vendor(form_response) move_applicant_to_idv_session idv_session.mark_verify_info_step_complete! @@ -251,21 +252,38 @@ def save_threatmetrix_status(form_response) idv_session.threatmetrix_review_status = review_status end + def save_source_check_vendor(form_response) + vendor = form_response.extra.dig( + :proofing_results, + :context, + :stages, + :state_id, + :vendor_name, + ) + idv_session.source_check_vendor = vendor + end + def summarize_result_and_rate_limit(summary_result) proofing_results_exception = summary_result.extra.dig(:proofing_results, :exception) resolution_rate_limiter.increment! if proofing_results_exception.blank? if summary_result.success? - add_proofing_components + add_proofing_components(summary_result) else idv_failure(summary_result) end end - def add_proofing_components + def add_proofing_components(summary_result) ProofingComponent.create_or_find_by(user: current_user).update( resolution_check: Idp::Constants::Vendors::LEXIS_NEXIS, - source_check: Idp::Constants::Vendors::AAMVA, + source_check: summary_result.extra.dig( + :proofing_results, + :context, + :stages, + :state_id, + :vendor_name, + ), ) end diff --git a/app/controllers/idv/in_person/verify_info_controller.rb b/app/controllers/idv/in_person/verify_info_controller.rb index 1eb612bb664..999aa3addb2 100644 --- a/app/controllers/idv/in_person/verify_info_controller.rb +++ b/app/controllers/idv/in_person/verify_info_controller.rb @@ -46,6 +46,7 @@ def self.step_info idv_session.resolution_successful = nil idv_session.verify_info_step_document_capture_session_uuid = nil idv_session.threatmetrix_review_status = nil + idv_session.source_check_vendor = nil idv_session.applicant = nil end, ) diff --git a/app/controllers/idv/verify_info_controller.rb b/app/controllers/idv/verify_info_controller.rb index bc11819486b..283fd647efc 100644 --- a/app/controllers/idv/verify_info_controller.rb +++ b/app/controllers/idv/verify_info_controller.rb @@ -52,6 +52,7 @@ def self.step_info end, undo_step: ->(idv_session:, user:) do idv_session.resolution_successful = nil + idv_session.source_check_vendor = nil idv_session.address_edited = nil idv_session.verify_info_step_document_capture_session_uuid = nil idv_session.threatmetrix_review_status = nil diff --git a/app/services/idv/proofing_components.rb b/app/services/idv/proofing_components.rb index f5b2a6e64e3..38c15866ccd 100644 --- a/app/services/idv/proofing_components.rb +++ b/app/services/idv/proofing_components.rb @@ -33,7 +33,7 @@ def document_type end def source_check - Idp::Constants::Vendors::AAMVA if idv_session.verify_info_step_complete? + idv_session.source_check_vendor end def resolution_check @@ -67,7 +67,6 @@ def to_h address_check:, threatmetrix:, threatmetrix_review_status:, - }.compact end diff --git a/app/services/idv/session.rb b/app/services/idv/session.rb index abc19910394..d31c0d143a5 100644 --- a/app/services/idv/session.rb +++ b/app/services/idv/session.rb @@ -1,6 +1,46 @@ # frozen_string_literal: true module Idv + # @attr address_edited [Boolean, nil] + # @attr address_verification_mechanism [String, nil] + # @attr applicant [Struct, nil] + # @attr document_capture_session_uuid [String, nil] + # @attr flow_path [String, nil] + # @attr go_back_path [String, nil] + # @attr gpo_code_verified [Boolean, nil] + # @attr had_barcode_attention_error [Boolean, nil] + # @attr had_barcode_read_failure [Boolean, nil] + # @attr idv_consent_given [Boolean, nil] + # @attr idv_consent_given_at [String, nil] + # @attr idv_phone_step_document_capture_session_uuid [String, nil] + # @attr mail_only_warning_shown [Boolean, nil] + # @attr opted_in_to_in_person_proofing [Boolean, nil] + # @attr personal_key [String, nil] + # @attr personal_key_acknowledged [Boolean, nil] + # @attr phone_for_mobile_flow [String, nil] + # @attr previous_phone_step_params [Array] + # @attr previous_ssn [String, nil] + # @attr profile_id [String, nil] + # @attr proofing_started_at [String, nil] + # @attr redo_document_capture [Boolean, nil] + # @attr resolution_successful [Boolean, nil] + # @attr selfie_check_performed [Boolean, nil] + # @attr selfie_check_required [Boolean, nil] + # @attr skip_doc_auth [Boolean, nil] + # @attr skip_doc_auth_from_handoff [Boolean, nil] + # @attr skip_doc_auth_from_how_to_verify [Boolean, nil] + # @attr skip_hybrid_handoff [Boolean, nil] + # @attr source_check_vendor [String, nil] + # @attr ssn [String, nil] + # @attr threatmetrix_review_status [String, nil] + # @attr threatmetrix_session_id [String, nil] + # @attr user_phone_confirmation [Boolean, nil] + # @attr vendor_phone_confirmation [Boolean, nil] + # @attr verify_info_step_document_capture_session_uuid [String, nil] + # @attr welcome_visited [Boolean, nil] + # @attr_reader current_user [User] + # @attr_reader gpo_otp [String, nil] + # @attr_reader service_provider [ServiceProvider] class Session VALID_SESSION_ATTRIBUTES = %i[ address_edited @@ -25,6 +65,7 @@ class Session profile_id proofing_started_at redo_document_capture + source_check_vendor resolution_successful selfie_check_performed selfie_check_required diff --git a/app/services/proofing/resolution/plugins/aamva_plugin.rb b/app/services/proofing/resolution/plugins/aamva_plugin.rb index f516efb5386..979bd3fd5ef 100644 --- a/app/services/proofing/resolution/plugins/aamva_plugin.rb +++ b/app/services/proofing/resolution/plugins/aamva_plugin.rb @@ -59,7 +59,7 @@ def out_of_aamva_jurisdiction_result errors: {}, exception: nil, success: true, - vendor_name: 'UnsupportedJurisdiction', + vendor_name: Idp::Constants::Vendors::AAMVA_UNSUPPORTED_JURISDICTION, ) end diff --git a/lib/idp/constants.rb b/lib/idp/constants.rb index d7ba925e42d..77510830474 100644 --- a/lib/idp/constants.rb +++ b/lib/idp/constants.rb @@ -16,6 +16,9 @@ module Vendors MOCK = 'mock' USPS = 'usps' AAMVA = 'aamva' + AAMVA_UNSUPPORTED_JURISDICTION = 'UnsupportedJurisdiction' + STATE_ID_MOCK = 'StateIdMock' + SOURCE_CHECK = [AAMVA, AAMVA_UNSUPPORTED_JURISDICTION, STATE_ID_MOCK].freeze end # US State and Territory codes are diff --git a/spec/controllers/idv/verify_info_controller_spec.rb b/spec/controllers/idv/verify_info_controller_spec.rb index 5b8e6e758c0..7dacf98adb1 100644 --- a/spec/controllers/idv/verify_info_controller_spec.rb +++ b/spec/controllers/idv/verify_info_controller_spec.rb @@ -396,10 +396,6 @@ end context 'for an aamva request' do - before do - allow(controller).to receive(:load_async_state).and_return(async_state) - end - let(:document_capture_session) do DocumentCaptureSession.create(user:) end @@ -407,7 +403,7 @@ let(:success) { true } let(:errors) { {} } let(:exception) { nil } - let(:vendor_name) { :aamva } + let(:vendor_name) { 'aamva_placeholder' } let(:async_state) do # Here we're trying to match the store to redis -> read from redis flow this data travels @@ -436,6 +432,10 @@ document_capture_session.load_proofing_result end + before do + allow(controller).to receive(:load_async_state).and_return(async_state) + end + context 'when aamva processes the request normally' do it 'redirect to phone confirmation url' do put :show @@ -458,7 +458,12 @@ event = @analytics.events['IdV: doc auth verify proofing results'].first state_id = event.dig(:proofing_results, :context, :stages, :state_id) - expect(state_id).to match(a_hash_including(state_id_type: 'drivers_license')) + expect(state_id).to match( + hash_including( + state_id_type: 'drivers_license', + vendor_name: 'aamva_placeholder', + ), + ) end end diff --git a/spec/features/idv/analytics_spec.rb b/spec/features/idv/analytics_spec.rb index 606eb9373ec..dbe44ada457 100644 --- a/spec/features/idv/analytics_spec.rb +++ b/spec/features/idv/analytics_spec.rb @@ -41,7 +41,7 @@ { document_check: 'mock', document_type: 'state_id', - source_check: 'aamva', + source_check: 'StateIdMock', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', @@ -590,54 +590,54 @@ }, 'IdV: phone confirmation form' => { success: true, errors: {}, phone_type: :mobile, types: [:fixed_or_mobile], carrier: 'Test Mobile Carrier', country_code: 'US', area_code: '202', otp_delivery_preference: 'sms', - proofing_components: { document_check: 'usps', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', source_check: 'aamva' } + proofing_components: { document_check: 'usps', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', source_check: 'StateIdMock' } }, 'IdV: phone confirmation vendor' => { success: true, errors: {}, vendor: { exception: nil, vendor_name: 'AddressMock', transaction_id: 'address-mock-transaction-id-123', timed_out: false, reference: '' }, new_phone_added: false, hybrid_handoff_phone_used: false, area_code: '202', country_code: 'US', phone_fingerprint: anything, - proofing_components: { address_check: 'lexis_nexis_address', document_check: 'usps', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', source_check: 'aamva' } + proofing_components: { address_check: 'lexis_nexis_address', document_check: 'usps', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', source_check: 'StateIdMock' } }, 'IdV: phone confirmation otp sent' => { success: true, otp_delivery_preference: :sms, country_code: 'US', area_code: '202', adapter: :test, errors: {}, phone_fingerprint: anything, rate_limit_exceeded: false, telephony_response: anything, - proofing_components: { address_check: 'lexis_nexis_address', document_check: 'usps', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', source_check: 'aamva' } + proofing_components: { address_check: 'lexis_nexis_address', document_check: 'usps', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', source_check: 'StateIdMock' } }, 'IdV: phone confirmation otp visited' => { - proofing_components: { address_check: 'lexis_nexis_address', document_check: 'usps', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', source_check: 'aamva' }, + proofing_components: { address_check: 'lexis_nexis_address', document_check: 'usps', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', source_check: 'StateIdMock' }, }, 'IdV: phone confirmation otp submitted' => { success: true, code_expired: false, code_matches: true, otp_delivery_preference: :sms, second_factor_attempts_count: 0, errors: {}, - proofing_components: { document_check: 'usps', source_check: 'aamva', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } + proofing_components: { document_check: 'usps', source_check: 'StateIdMock', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } }, :idv_enter_password_visited => { address_verification_method: 'phone', - proofing_components: { document_check: 'usps', source_check: 'aamva', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' }, + proofing_components: { document_check: 'usps', source_check: 'StateIdMock', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' }, }, :idv_enter_password_submitted => { success: true, fraud_review_pending: false, fraud_rejection: false, gpo_verification_pending: false, in_person_verification_pending: true, proofing_workflow_time_in_seconds: 0.0, - proofing_components: { document_check: 'usps', source_check: 'aamva', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } + proofing_components: { document_check: 'usps', source_check: 'StateIdMock', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } }, 'IdV: final resolution' => { success: true, fraud_review_pending: false, fraud_rejection: false, gpo_verification_pending: false, in_person_verification_pending: true, proofing_workflow_time_in_seconds: 0.0, # NOTE: pending_profile_idv_level should be set here, a nil value is cached for current_user.pending_profile. profile_history: match_array(kind_of(Idv::ProfileLogging)), - proofing_components: { document_check: 'usps', source_check: 'aamva', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } + proofing_components: { document_check: 'usps', source_check: 'StateIdMock', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } }, 'IdV: personal key visited' => { in_person_verification_pending: true, address_verification_method: 'phone', encrypted_profiles_missing: false, pending_profile_idv_level: idv_level, - proofing_components: { document_check: 'usps', source_check: 'aamva', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } + proofing_components: { document_check: 'usps', source_check: 'StateIdMock', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } }, 'IdV: personal key acknowledgment toggled' => { checked: true, pending_profile_idv_level: idv_level, - proofing_components: { document_check: 'usps', source_check: 'aamva', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } + proofing_components: { document_check: 'usps', source_check: 'StateIdMock', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } }, 'IdV: personal key submitted' => { address_verification_method: 'phone', fraud_review_pending: false, fraud_rejection: false, in_person_verification_pending: true, pending_profile_idv_level: idv_level, - proofing_components: { document_check: 'usps', source_check: 'aamva', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } + proofing_components: { document_check: 'usps', source_check: 'StateIdMock', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' } }, 'IdV: in person ready to verify visited' => { pending_profile_idv_level: idv_level, - proofing_components: { document_check: 'usps', source_check: 'aamva', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' }, + proofing_components: { document_check: 'usps', source_check: 'StateIdMock', resolution_check: 'lexis_nexis', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass', address_check: 'lexis_nexis_address' }, }, 'IdV: user clicked what to bring link on ready to verify page' => {}, 'IdV: user clicked sp link on ready to verify page' => {}, @@ -974,6 +974,7 @@ end end end + context 'Hybrid flow' do context 'facial comparison not required - Happy path' do before do @@ -1038,6 +1039,7 @@ end end end + context 'facial comparison required - Happy path' do before do allow_any_instance_of(DocAuth::Response).to receive(:selfie_status).and_return(:success) @@ -1097,6 +1099,7 @@ end end end + context 'facial comparison not required - Happy path' do before do allow(Telephony).to receive(:send_doc_auth_link).and_wrap_original do |impl, config| diff --git a/spec/features/idv/end_to_end_idv_spec.rb b/spec/features/idv/end_to_end_idv_spec.rb index 8757ec07bdc..055e011cb7a 100644 --- a/spec/features/idv/end_to_end_idv_spec.rb +++ b/spec/features/idv/end_to_end_idv_spec.rb @@ -268,7 +268,9 @@ def validate_verify_info_page def validate_verify_info_submit(user) expect(page).to have_content(t('doc_auth.forms.doc_success')) expect(user.proofing_component.resolution_check).to eq(Idp::Constants::Vendors::LEXIS_NEXIS) - expect(user.proofing_component.source_check).to eq(Idp::Constants::Vendors::AAMVA) + expect(user.proofing_component.source_check).to satisfy do |v| + Idp::Constants::Vendors::SOURCE_CHECK.include?(v) + end end def validate_phone_page diff --git a/spec/features/idv/proofing_components_spec.rb b/spec/features/idv/proofing_components_spec.rb index a12f58ad57f..19975e08a5d 100644 --- a/spec/features/idv/proofing_components_spec.rb +++ b/spec/features/idv/proofing_components_spec.rb @@ -31,6 +31,7 @@ proofing_components = user.active_profile.proofing_components expect(proofing_components['document_check']).to eq('mock') expect(proofing_components['document_type']).to eq('state_id') + expect(proofing_components['source_check']).to eq('StateIdMock') end end end diff --git a/spec/services/idv/proofing_components_spec.rb b/spec/services/idv/proofing_components_spec.rb index 97e78cc5ab6..8c871f87725 100644 --- a/spec/services/idv/proofing_components_spec.rb +++ b/spec/services/idv/proofing_components_spec.rb @@ -38,6 +38,7 @@ allow(FeatureManagement).to receive(:proofing_device_profiling_collecting_enabled?). and_return(true) idv_session.threatmetrix_review_status = 'pass' + idv_session.source_check_vendor = 'aamva' end it 'returns expected result' do @@ -63,6 +64,7 @@ context 'in-person proofing' do context 'establishing' do let!(:enrollment) { create(:in_person_enrollment, :establishing, user:) } + it 'returns USPS' do expect(subject.document_check).to eql(Idp::Constants::Vendors::USPS) end @@ -70,6 +72,7 @@ context 'pending' do let!(:enrollment) { create(:in_person_enrollment, :pending, user:) } + it 'returns USPS' do expect(subject.document_check).to eql(Idp::Constants::Vendors::USPS) end @@ -80,13 +83,16 @@ before do allow(IdentityConfig.store).to receive(:doc_auth_vendor_default).and_return('test_vendor') end + context 'before doc auth complete' do it 'returns nil' do expect(subject.document_check).to be_nil end end + context 'after doc auth completed successfully' do let(:pii_from_doc) { Idp::Constants::MOCK_IDV_APPLICANT } + it 'returns doc auth vendor' do expect(subject.document_check).to eql('test_vendor') end @@ -98,6 +104,7 @@ context 'in-person proofing' do context 'establishing' do let!(:enrollment) { create(:in_person_enrollment, :establishing, user:) } + it 'returns nil' do expect(subject.document_type).to be_nil end @@ -105,6 +112,7 @@ context 'pending' do let!(:enrollment) { create(:in_person_enrollment, :pending, user:) } + it 'returns nil' do expect(subject.document_type).to be_nil end @@ -117,8 +125,10 @@ expect(subject.document_type).to be_nil end end + context 'after doc auth completed successfully' do let(:pii_from_doc) { Idp::Constants::MOCK_IDV_APPLICANT } + it 'returns doc auth vendor' do expect(subject.document_type).to eql('state_id') end @@ -134,6 +144,7 @@ context 'after verification' do before do idv_session.mark_verify_info_step_complete! + idv_session.source_check_vendor = 'aamva' end it 'returns aamva' do @@ -195,10 +206,12 @@ before do idv_session.threatmetrix_review_status = 'pass' end + it 'returns true' do expect(subject.threatmetrix).to be_truthy end end + context 'threatmetrix_review_status not present' do it 'returns nil' do expect(subject.threatmetrix).to be_nil @@ -216,6 +229,7 @@ before do idv_session.threatmetrix_review_status = 'pass' end + it 'returns false' do expect(subject.threatmetrix).to eql(false) end @@ -234,10 +248,12 @@ before do idv_session.threatmetrix_review_status = 'pass' end + it 'returns value' do expect(subject.threatmetrix_review_status).to eql('pass') end end + context 'threatmetrix_review_status not present in idv_session' do it 'returns nil' do expect(subject.threatmetrix_review_status).to be_nil From 8a84353c0bae7a9b33d99df13d5ca5542ab8810f Mon Sep 17 00:00:00 2001 From: Lauren George Date: Tue, 19 Nov 2024 17:11:07 -0500 Subject: [PATCH 2/2] Handle 50/50 state for new Idv::Session key --- app/services/idv/proofing_components.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/services/idv/proofing_components.rb b/app/services/idv/proofing_components.rb index 38c15866ccd..21d097d4ab4 100644 --- a/app/services/idv/proofing_components.rb +++ b/app/services/idv/proofing_components.rb @@ -2,12 +2,7 @@ module Idv class ProofingComponents - def initialize( - idv_session:, - session:, - user:, - user_session: - ) + def initialize(idv_session:, session:, user:, user_session:) @idv_session = idv_session @session = session @user = user @@ -33,7 +28,8 @@ def document_type end def source_check - idv_session.source_check_vendor + idv_session.source_check_vendor.presence || + (idv_session.verify_info_step_complete? && Idp::Constants::Vendors::AAMVA) end def resolution_check