);
}
diff --git a/app/javascript/packages/document-capture/context/in-person.ts b/app/javascript/packages/document-capture/context/in-person.ts
index 5639c0c4c6d..54c042eaa48 100644
--- a/app/javascript/packages/document-capture/context/in-person.ts
+++ b/app/javascript/packages/document-capture/context/in-person.ts
@@ -50,6 +50,12 @@ export interface InPersonContextProps {
*/
skipDocAuthFromSocure?: boolean;
+ /**
+ * path to choose ID type page, used when passports is enabled
+ */
+
+ chooseIdTypePath?: string;
+
/**
* URL for Opt-in IPP, used when in_person_proofing_opt_in_enabled is enabled
*/
diff --git a/app/javascript/packs/document-capture.tsx b/app/javascript/packs/document-capture.tsx
index 9ce2c72e38d..b4001330c2e 100644
--- a/app/javascript/packs/document-capture.tsx
+++ b/app/javascript/packs/document-capture.tsx
@@ -41,6 +41,7 @@ interface AppRootData {
howToVerifyURL: string;
socureErrorsTimeoutURL: string;
previousStepUrl: string;
+ chooseIdTypePath: string;
docAuthPassportsEnabled: string;
docAuthSelfieDesktopTestMode: string;
docAuthUploadEnabled: string;
@@ -123,6 +124,7 @@ const {
howToVerifyUrl,
socureErrorsTimeoutUrl,
previousStepUrl,
+ chooseIdTypePath,
docAuthPassportsEnabled,
docAuthSelfieDesktopTestMode,
locationsUrl: locationsURL,
@@ -152,6 +154,7 @@ render(
skipDocAuthFromHandoff: skipDocAuthFromHandoff === 'true',
skipDocAuthFromSocure: skipDocAuthFromSocure === 'true',
howToVerifyURL: howToVerifyUrl,
+ chooseIdTypePath,
socureErrorsTimeoutURL: socureErrorsTimeoutUrl,
passportEnabled: String(docAuthPassportsEnabled) === 'true',
previousStepURL: previousStepUrl,
diff --git a/app/jobs/data_warehouse/table_summary_stats_export_job.rb b/app/jobs/data_warehouse/table_summary_stats_export_job.rb
index d54437dca0d..19fee242246 100644
--- a/app/jobs/data_warehouse/table_summary_stats_export_job.rb
+++ b/app/jobs/data_warehouse/table_summary_stats_export_job.rb
@@ -37,41 +37,81 @@ def fetch_log_group_counts(timestamp)
to: timestamp.end_of_day,
)[0]
# set row count to 0 if nil or else convert to int
- result[table_name].nil? ? result[table_name] =
- { row_count: 0 } : result[table_name]['row_count'] =
- result[table_name]['row_count'].to_i
+ offset = get_offset_count(log_group_name, timestamp)
+ if result[table_name].nil?
+ result[table_name] = { row_count: 0 }
+ else
+ result[table_name]['row_count'] = result[table_name]['row_count'].to_i - offset
+ end
end
end
def log_groups
- env = Identity::Hostdata.env
[
"#{env}_/srv/idp/shared/log/events.log",
"#{env}_/srv/idp/shared/log/production.log",
]
end
- def cloudwatch_client(log_group_name: nil)
+ def env
+ Identity::Hostdata.env
+ end
+
+ def cloudwatch_client(log_group_name: nil, slice_interval: 1.day)
Reporting::CloudwatchClient.new(
log_group_name: log_group_name,
ensure_complete_logs: false,
+ num_threads: 6,
+ slice_interval: slice_interval,
)
end
- def cloudwatch_query(log_group_name)
- base_log_group = "#{Identity::Hostdata.env}_/srv/idp/shared/log"
- log_stream_filter_map = {
+ def log_stream_filter_map
+ base_log_group = "#{env}_/srv/idp/shared/log"
+ {
"#{base_log_group}/events.log" => "@logStream like 'worker-i-' or @logStream like 'idp-i-'",
"#{base_log_group}/production.log" => "@logStream like 'idp-i-'",
}
+ end
+
+ def cloudwatch_query(log_group_name)
<<~QUERY
- fields @timestamp
+ fields jsonParse(@message) as @messageJson
| filter #{log_stream_filter_map[log_group_name]}
- | filter @message like /\\{.*/
+ | filter isPresent(@messageJson)
| stats count() as row_count
QUERY
end
+ def production_offset_query
+ log_group_name = "#{env}_/srv/idp/shared/log/production.log"
+ <<~QUERY
+ fields jsonParse(@message) as @messageJson, concat(@timestamp, @message) as ts_plus_message
+ | filter #{log_stream_filter_map[log_group_name]}
+ | filter isPresent(@messageJson)
+ | stats count() as cnt by ts_plus_message
+ | stats sum(cnt - 1) as offset_count
+ QUERY
+ end
+
+ def get_offset_count(log_group_name, timestamp)
+ if log_group_name == "#{env}_/srv/idp/shared/log/production.log"
+ # For production logs, exclude count of duplicates with same message & timestamp
+ cw_client = cloudwatch_client(
+ log_group_name: log_group_name,
+ slice_interval: 30.minutes,
+ )
+ result = cw_client.fetch(
+ query: production_offset_query,
+ from: timestamp.beginning_of_day,
+ to: timestamp.end_of_day,
+ )
+ result.sum { |h| h['offset_count'].to_i }
+ else
+ 0
+ end
+ end
+
def fetch_table_max_ids_and_counts(timestamp)
Reports::BaseReport.transaction_with_timeout do
max_ids_and_counts(timestamp)
diff --git a/app/jobs/reports/irs_verification_demographics_report.rb b/app/jobs/reports/irs_verification_demographics_report.rb
new file mode 100644
index 00000000000..1e20f6cf6b8
--- /dev/null
+++ b/app/jobs/reports/irs_verification_demographics_report.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+require 'csv'
+require 'reporting/irs_verification_demographics_report'
+
+module Reports
+ class IrsVerificationDemographicsReport < BaseReport
+ REPORT_NAME = 'irs-verification-demographics-report'
+
+ attr_reader :report_date
+
+ def initialize(report_date = nil, *args, **rest)
+ @report_date = report_date
+ super(*args, **rest)
+ end
+
+ def perform(date = Time.zone.yesterday.end_of_day)
+ @report_date = date
+
+ email_addresses = emails.select(&:present?)
+ if email_addresses.empty?
+ Rails.logger.warn 'No email addresses - IRS Verification Demographics Report NOT SENT'
+ return false
+ end
+
+ reports.each do |report|
+ upload_to_s3(report.table, report_name: report.filename)
+ end
+
+ ReportMailer.tables_report(
+ email: email_addresses,
+ subject: "IRS Verification Demographics Metrics Report - #{report_date.to_date}",
+ reports: reports,
+ message: preamble,
+ attachment_format: :csv,
+ ).deliver_now
+ end
+
+ # Explanatory text to go before the report in the email
+ # @return [String]
+ def preamble(env: Identity::Hostdata.env || 'local')
+ ERB.new(<<~ERB).result(binding).html_safe # rubocop:disable Rails/OutputSafety
+ <% if env != 'prod' %>
+
+
+ <%#
+ NOTE: our AlertComponent doesn't support heading content like this uses,
+ so for a one-off outside the Rails pipeline it was easier to inline the HTML here.
+ %>
+
+ Non-Production Report
+
+
+ This was generated in the <%= env %> environment.
+
diff --git a/app/views/idv/hybrid_mobile/document_capture/show.html.erb b/app/views/idv/hybrid_mobile/document_capture/show.html.erb
index dff2ad06368..402de56796a 100644
--- a/app/views/idv/hybrid_mobile/document_capture/show.html.erb
+++ b/app/views/idv/hybrid_mobile/document_capture/show.html.erb
@@ -13,6 +13,7 @@
skip_doc_auth_from_handoff: nil,
skip_doc_auth_from_socure: skip_doc_auth_from_socure,
socure_errors_timeout_url: socure_errors_timeout_url,
+ choose_id_type_path: choose_id_type_path,
doc_auth_selfie_capture: doc_auth_selfie_capture,
doc_auth_upload_enabled: doc_auth_upload_enabled,
mock_client: mock_client,
diff --git a/app/views/idv/link_sent/show.html.erb b/app/views/idv/link_sent/show.html.erb
index b3bb506b4ef..4bef8552cde 100644
--- a/app/views/idv/link_sent/show.html.erb
+++ b/app/views/idv/link_sent/show.html.erb
@@ -10,7 +10,7 @@
<% self.title = t('titles.doc_auth.link_sent') %>
<%= render AlertComponent.new(type: :warning, class: 'margin-bottom-4') do %>
- <%= t('doc_auth.info.keep_window_open') %>
+ <%= t('doc_auth.info.keep_window_open') %>
<% if FeatureManagement.doc_capture_polling_enabled? %>
<%= t('doc_auth.info.link_sent_complete_polling') %>
<% else %>
diff --git a/app/views/idv/shared/_document_capture.html.erb b/app/views/idv/shared/_document_capture.html.erb
index b843553c8df..48257ef5b66 100644
--- a/app/views/idv/shared/_document_capture.html.erb
+++ b/app/views/idv/shared/_document_capture.html.erb
@@ -35,6 +35,7 @@
in_person_outage_message_enabled: IdentityConfig.store.in_person_outage_message_enabled,
in_person_outage_expected_update_date: IdentityConfig.store.in_person_outage_expected_update_date,
us_states_territories: @presenter.usps_states_territories,
+ choose_id_type_path: choose_id_type_path,
doc_auth_passports_enabled: IdentityConfig.store.doc_auth_passports_enabled,
doc_auth_selfie_capture: doc_auth_selfie_capture,
doc_auth_selfie_desktop_test_mode: IdentityConfig.store.doc_auth_selfie_desktop_test_mode,
diff --git a/app/views/idv/shared/choose_id_type.html.erb b/app/views/idv/shared/choose_id_type.html.erb
index e146c5e7122..853f35b1c40 100644
--- a/app/views/idv/shared/choose_id_type.html.erb
+++ b/app/views/idv/shared/choose_id_type.html.erb
@@ -11,8 +11,11 @@
<% if presenter.hybrid_flow? %>
<%= render AlertComponent.new(type: :warning, class: 'margin-bottom-4') do %>
- <%= t('doc_auth.info.login_access_sp', app_name: APP_NAME, sp_name: decorated_sp_session.sp_name) %>
- <%= t('doc_auth.info.add_id_consent_with_phone', app_name: APP_NAME) %>
+ <%= t(
+ 'doc_auth.hybrid_flow_warning.explanation_html',
+ app_name: APP_NAME,
+ service_provider_name: decorated_sp_session.sp_name,
+ ) %>
<% end %>
<% end %>
diff --git a/config/application.yml.default b/config/application.yml.default
index 4321f7bdc85..26e2f01bd38 100644
--- a/config/application.yml.default
+++ b/config/application.yml.default
@@ -107,8 +107,6 @@ doc_auth_client_sharpness_threshold: 50
doc_auth_error_dpi_threshold: 290
doc_auth_error_glare_threshold: 40
doc_auth_error_sharpness_threshold: 40
-doc_auth_manual_upload_disabled_a_b_testing_enabled: false
-doc_auth_manual_upload_disabled_a_b_testing_percent: 0
doc_auth_max_attempts: 5
doc_auth_max_capture_attempts_before_native_camera: 3
doc_auth_max_submission_attempts_before_native_camera: 3
diff --git a/config/initializers/ab_tests.rb b/config/initializers/ab_tests.rb
index dc88ef9bd62..3a3d52302b4 100644
--- a/config/initializers/ab_tests.rb
+++ b/config/initializers/ab_tests.rb
@@ -168,18 +168,6 @@ def self.all
user&.uuid
end.freeze
- DOC_AUTH_MANUAL_UPLOAD_DISABLED = AbTest.new(
- experiment_name: 'Doc Auth Manual Upload Disabled',
- should_log: /^idv/i,
- buckets: {
- manual_upload_disabled:
- IdentityConfig.store.doc_auth_manual_upload_disabled_a_b_testing_enabled ?
- IdentityConfig.store.doc_auth_manual_upload_disabled_a_b_testing_percent : 0,
- },
- ) do |service_provider:, session:, user:, user_session:, **|
- user&.uuid
- end.freeze
-
PROOFING_VENDOR = AbTest.new(
experiment_name: 'Proofing Vendor',
should_log: /^idv/i,
diff --git a/config/initializers/job_configurations.rb b/config/initializers/job_configurations.rb
index 47d5e03ff7b..866a04f7850 100644
--- a/config/initializers/job_configurations.rb
+++ b/config/initializers/job_configurations.rb
@@ -10,6 +10,7 @@
cron_every_monday_1am = 'every Monday at 1:00 UTC' # equivalent to '0 1 * * 1'
cron_every_monday_2am = 'every Monday at 2:00 UTC' # equivalent to '0 2 * * 1'
cron_monthly = '30 0 1 * *' # monthly, 0:30 UTC to not overlap with jobs running at 0000
+cron_quarterly = '0 0 1 1,4,7,10 *' # quarterly
s3_cron_24h = '0 6 * * *' # 6am UTC is 1am EST/2am EDT
if defined?(Rails::Console)
@@ -291,6 +292,12 @@
cron: cron_monthly,
args: -> { [Time.zone.yesterday.end_of_day] },
},
+ # Send irs quarterly metrics to Team Data
+ irs_verification_demographics_report: {
+ class: 'Reports::IrsVerificationDemographicsReport',
+ cron: cron_quarterly,
+ args: -> { [Time.zone.yesterday.end_of_day] },
+ },
# Download and store Socure reason codes
socure_reason_code_download: {
class: 'SocureReasonCodeDownloadJob',
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 845a6b05e06..94c0acd5432 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -551,7 +551,10 @@ doc_auth.errors.file_type.invalid: This file type is not accepted, please choose
doc_auth.errors.general.fallback_field_level: Please add a new image
doc_auth.errors.general.multiple_back_id_failures: We couldn’t verify the back of your ID. Try taking a new picture.
doc_auth.errors.general.multiple_front_id_failures: We couldn’t verify the front of your ID. Try taking a new picture.
-doc_auth.errors.general.network_error: We are having technical difficulties on our end. Please try to submit your images again later.
+doc_auth.errors.general.network_error: We are having technical difficulties verifying your ID. Try again or come back later if you continue to see this error.
+doc_auth.errors.general.network_error_passport: We are having technical difficulties verifying your passport. Try again or
+doc_auth.errors.general.network_error_passport_ending: if you have one.
+doc_auth.errors.general.network_error_passport_link_text: use another type of ID
doc_auth.errors.general.new_network_error: Try again later.
doc_auth.errors.general.no_liveness: Try taking new pictures.
doc_auth.errors.general.selfie_failure: We couldn’t verify the photo of yourself. Try taking a new picture.
@@ -634,13 +637,8 @@ doc_auth.headings.verify_at_post_office: Go to a participating Post Office
doc_auth.headings.verify_identity: Verify your identity
doc_auth.headings.verify_online: Verify your identity online
doc_auth.headings.welcome: Let’s verify your identity for %{sp_name}
-doc_auth.hybrid_flow_warning.explanation_html: You’re using %{app_name} to verify your identity for access to %{service_provider_name} and its services.
+doc_auth.hybrid_flow_warning.explanation_html: You’re using %{app_name} to access %{service_provider_name}. Only add your ID if you asked %{app_name} to verify your ID using your phone.
doc_auth.hybrid_flow_warning.explanation_non_sp_html: You’re using %{app_name} to verify your identity.
-doc_auth.hybrid_flow_warning.only_add_if_text: 'ONLY ADD YOUR ID IF:'
-doc_auth.hybrid_flow_warning.only_add_own_account: You are using your own %{app_name} account
-doc_auth.hybrid_flow_warning.only_add_phone_verify: You asked %{app_name} to verify your ID using your phone
-doc_auth.hybrid_flow_warning.only_add_sp_services_html: You are trying to access %{service_provider_name} services
-doc_auth.info.add_id_consent_with_phone: Only add your ID if you asked %{app_name} to verify your ID using your phone.
doc_auth.info.address: If your residential address and mailing address are different, you can also try to verify your mailing address.
doc_auth.info.address_guidance_puerto_rico_html: Puerto Rico residents:
Edit your address to list your urbanization or condominium on address line 2.
doc_auth.info.capture_status_big_document: Too Close
@@ -667,8 +665,7 @@ doc_auth.info.learn_more: Learn more about how we protect your sensitive informa
doc_auth.info.lets_go: 'Identity verification happens in two parts:'
doc_auth.info.link_sent: Please check your phone and follow instructions to take a photo of your ID.
doc_auth.info.link_sent_complete_no_polling: When you are done, click Continue here to finish verifying your identity.
-doc_auth.info.link_sent_complete_polling: The next step will load automatically.
-doc_auth.info.login_access_sp: You’re using %{app_name} to access %{sp_name}.
+doc_auth.info.link_sent_complete_polling: The next step will load automatically after you verify your ID on your phone.
doc_auth.info.mailing_address: We’ll mail the letter with a verification code to this address.
doc_auth.info.no_ssn: You must have a Social Security number to finish verifying your identity.
doc_auth.info.passport_capture: Take a photo of the data page of your passport book. This page has your passport photo and personal information.
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 3c1cf5b528b..9ce32083a18 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -562,7 +562,10 @@ doc_auth.errors.file_type.invalid: No se acepta este tipo de archivo; elija un a
doc_auth.errors.general.fallback_field_level: Agregue una imagen nueva
doc_auth.errors.general.multiple_back_id_failures: No pudimos verificar el reverso de su identificación. Intente tomar una nueva foto.
doc_auth.errors.general.multiple_front_id_failures: No pudimos verificar el frente de su identificación. Intente tomar una nueva foto.
-doc_auth.errors.general.network_error: Estamos teniendo problemas técnicos. Intente enviar sus imágenes de nuevo más tarde.
+doc_auth.errors.general.network_error: Estamos teniendo problemas técnicos para verificar su identidad. Vuelva a intentarlo o regrese más tarde si sigue recibiendo este error.
+doc_auth.errors.general.network_error_passport: Estamos teniendo problemas técnicos para verificar su pasaporte. Vuelva a intentarlo o
+doc_auth.errors.general.network_error_passport_ending: si la tiene.
+doc_auth.errors.general.network_error_passport_link_text: use otro tipo de identificación.
doc_auth.errors.general.new_network_error: Vuelva a intentarlo más tarde.
doc_auth.errors.general.no_liveness: Intente tomar nuevas fotos.
doc_auth.errors.general.selfie_failure: No pudimos verificar su foto. Intente tomar una nueva foto.
@@ -645,13 +648,8 @@ doc_auth.headings.verify_at_post_office: Vaya a una oficina de correos participa
doc_auth.headings.verify_identity: Verifique su identidad
doc_auth.headings.verify_online: Verifique su identidad en línea
doc_auth.headings.welcome: Verifiquemos su identidad para %{sp_name}
-doc_auth.hybrid_flow_warning.explanation_html: Está utilizando %{app_name} para verificar su identidad y acceder a %{service_provider_name} y sus servicios.
+doc_auth.hybrid_flow_warning.explanation_html: Está usando %{app_name} para acceder a %{service_provider_name}. Solo agregue su identificación si solicitó a %{app_name} verificar su identidad usando su teléfono.
doc_auth.hybrid_flow_warning.explanation_non_sp_html: Está utilizando %{app_name} para verificar su identidad.
-doc_auth.hybrid_flow_warning.only_add_if_text: 'SOLO AGREGUE SU IDENTIFICACIÓN SI:'
-doc_auth.hybrid_flow_warning.only_add_own_account: Está usando su propia cuenta de %{app_name}
-doc_auth.hybrid_flow_warning.only_add_phone_verify: Usted solicitó a %{app_name} que verificara su identificación con su teléfono
-doc_auth.hybrid_flow_warning.only_add_sp_services_html: Está tratando de acceder a los servicios de %{service_provider_name}
-doc_auth.info.add_id_consent_with_phone: Solo agregue su identificación si solicitó a %{app_name} verificar su identidad usando su teléfono.
doc_auth.info.address: Si su domicilio y su dirección postal no son iguales, también puede intentar verificar su dirección postal.
doc_auth.info.address_guidance_puerto_rico_html: Residentes en Puerto Rico:
Edite su dirección para que el edificio de su vivienda o condominio figure en la línea de dirección 2.
doc_auth.info.capture_status_big_document: Demasiado cerca
@@ -678,8 +676,7 @@ doc_auth.info.learn_more: Obtenga más información sobre cómo protegemos su in
doc_auth.info.lets_go: 'La verificación de la identidad se efectúa en dos partes:'
doc_auth.info.link_sent: Revise su teléfono y siga las instrucciones para tomar una foto de su identificación.
doc_auth.info.link_sent_complete_no_polling: Cuando termine, haga clic en “Continuar” para terminar la verificación de su identidad.
-doc_auth.info.link_sent_complete_polling: El siguiente paso se cargará automáticamente.
-doc_auth.info.login_access_sp: Está usando %{app_name} para acceder a %{sp_name}.
+doc_auth.info.link_sent_complete_polling: El siguiente paso se cargará automáticamente después de que verifique su identidad en su teléfono.
doc_auth.info.mailing_address: Enviaremos la carta con un código de verificación a esta dirección.
doc_auth.info.no_ssn: Debe tener un número de Seguro Social para finalizar la verificación de su identidad.
doc_auth.info.passport_capture: Tome una fotografía de la página de datos de su pasaporte, es decir, de la página que muestra su foto y su información personal.
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index b08705ee6af..932b869ff2d 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -551,7 +551,10 @@ doc_auth.errors.file_type.invalid: Ce type de fichier n’est pas accepté ; ve
doc_auth.errors.general.fallback_field_level: Veuillez ajouter une nouvelle image
doc_auth.errors.general.multiple_back_id_failures: Nous n’avons pas pu vérifier le verso de votre pièce d’identité. Essayez de prendre une nouvelle photo.
doc_auth.errors.general.multiple_front_id_failures: Nous n’avons pas pu vérifier le recto de votre pièce d’identité. Essayez de prendre une nouvelle photo.
-doc_auth.errors.general.network_error: Nous rencontrons actuellement des difficultés techniques de notre côté. Veuillez réessayer d’envoyer vos images ultérieurement.
+doc_auth.errors.general.network_error: Nous rencontrons actuellement des difficultés techniques pour confirmer votre pièce d’identité. Veuillez réessayer ou revenir plus tard si le problème persiste.
+doc_auth.errors.general.network_error_passport: Nous rencontrons actuellement des difficultés techniques pour vérifier votre passeport. Veuillez réessayer ou
+doc_auth.errors.general.network_error_passport_ending: si vous en avez une.
+doc_auth.errors.general.network_error_passport_link_text: utiliser un autre type de pièce d’identité
doc_auth.errors.general.new_network_error: Veuillez réessayer ultérieurement.
doc_auth.errors.general.no_liveness: Essayez de prendre de nouvelles photos.
doc_auth.errors.general.selfie_failure: Nous n’avons pas pu vérifier votre photo. Essayez de prendre une nouvelle photo.
@@ -634,13 +637,8 @@ doc_auth.headings.verify_at_post_office: Vous rendre à un bureau de poste parti
doc_auth.headings.verify_identity: Confirmer votre identité
doc_auth.headings.verify_online: Confirmer votre identité en ligne
doc_auth.headings.welcome: Vérifions votre identité auprès de %{sp_name}
-doc_auth.hybrid_flow_warning.explanation_html: Vous utilisez %{app_name} pour confirmer votre identité et accéder à %{service_provider_name} et à ses services.
+doc_auth.hybrid_flow_warning.explanation_html: Vous utilisez %{app_name} pour accéder à %{service_provider_name}. Ajoutez uniquement votre pièce d’identité si vous avez demandé à %{app_name} de vérifier votre identité à l’aide de votre téléphone.
doc_auth.hybrid_flow_warning.explanation_non_sp_html: Vous utilisez %{app_name} pour confirmer votre identité.
-doc_auth.hybrid_flow_warning.only_add_if_text: 'N’AJOUTEZ VOTRE PIÈCE D’IDENTITÉ QUE SI :'
-doc_auth.hybrid_flow_warning.only_add_own_account: Vous utilisez votre propre compte %{app_name}
-doc_auth.hybrid_flow_warning.only_add_phone_verify: Vous avez demandé à %{app_name} de confirmer votre identité à l’aide de votre téléphone
-doc_auth.hybrid_flow_warning.only_add_sp_services_html: Vous essayez d’accéder aux services de %{service_provider_name}
-doc_auth.info.add_id_consent_with_phone: Ajoutez uniquement votre pièce d’identité si vous avez demandé à %{app_name} de vérifier votre identité à l’aide de votre téléphone.
doc_auth.info.address: Si votre adresse personnelle et votre adresse postale de contact sont différentes, vous pouvez également essayer de confirmer votre adresse postale.
doc_auth.info.address_guidance_puerto_rico_html: Résidents de Porto Rico :
modifiez votre adresse pour indiquer votre lotissement ou votre condominium à la ligne 2.
doc_auth.info.capture_status_big_document: Trop près
@@ -667,8 +665,7 @@ doc_auth.info.learn_more: En savoir plus sur la façon dont nous protégeons vos
doc_auth.info.lets_go: 'La vérification de l’identité se fait en deux temps :'
doc_auth.info.link_sent: Veuillez consulter votre téléphone et suivre les instructions pour prendre une photo de votre pièce d’identité.
doc_auth.info.link_sent_complete_no_polling: Quand vous aurez fini, cliquez sur « Suite » ici pour terminer la vérification de votre identité.
-doc_auth.info.link_sent_complete_polling: L’étape suivante se chargera automatiquement.
-doc_auth.info.login_access_sp: Vous utilisez %{app_name} pour accéder à %{sp_name}.
+doc_auth.info.link_sent_complete_polling: L’étape suivante se chargera automatiquement une fois que vous aurez confirmé votre identité sur votre téléphone.
doc_auth.info.mailing_address: Nous vous enverrons le courrier contenant un code de vérification à cette adresse.
doc_auth.info.no_ssn: Vous devez avoir un numéro de sécurité sociale pour terminer la vérification de votre identité.
doc_auth.info.passport_capture: Prenez une photo de la page d’informations de votre passeport. Cette page comporte votre photo d’identité et vos informations personnelles.
diff --git a/config/locales/zh.yml b/config/locales/zh.yml
index ba97423fadf..fa40f7d16be 100644
--- a/config/locales/zh.yml
+++ b/config/locales/zh.yml
@@ -562,7 +562,10 @@ doc_auth.errors.file_type.invalid: 这一文件类型我们不接受。请选择
doc_auth.errors.general.fallback_field_level: 请添加一个新图像
doc_auth.errors.general.multiple_back_id_failures: 我们无法验证你身份证件的背面。尝试重拍一张。
doc_auth.errors.general.multiple_front_id_failures: 我们无法验证你身份证件的正面。尝试重拍一张。
-doc_auth.errors.general.network_error: 我们这边有技术困难。请稍后再提交你的图像。
+doc_auth.errors.general.network_error: 我们在验证你的ID时遇到技术困难。如果你继续看到这个出错信息,请再试一下或稍后再试。
+doc_auth.errors.general.network_error_passport: 我们在验证你的护照时遇到技术困难。请再试一下,或
+doc_auth.errors.general.network_error_passport_ending: (如果有的话)。
+doc_auth.errors.general.network_error_passport_link_text: 使用其他类型的身份证件
doc_auth.errors.general.new_network_error: 请稍后再试。
doc_auth.errors.general.no_liveness: 尝试重拍。
doc_auth.errors.general.selfie_failure: 我们无法验证你自己的照片。请重拍一张。
@@ -645,13 +648,8 @@ doc_auth.headings.verify_at_post_office: 到一个参与本项目的邮局去
doc_auth.headings.verify_identity: 验证你的身份
doc_auth.headings.verify_online: 在网上验证身份
doc_auth.headings.welcome: 现在我们来为%{sp_name}验证你的身份
-doc_auth.hybrid_flow_warning.explanation_html: 你在使用 %{app_name} 验证身份以访问 %{service_provider_name} 及其服务。
+doc_auth.hybrid_flow_warning.explanation_html: 你在使用%{app_name}访问%{service_provider_name}。仅在你已请求%{app_name}使用你的电话来验证你的身份的情况下才添加你的身份证件。
doc_auth.hybrid_flow_warning.explanation_non_sp_html: 你在使用 %{app_name} 验证身份。
-doc_auth.hybrid_flow_warning.only_add_if_text: 只有在以下情况下才添加你的身份证件:
-doc_auth.hybrid_flow_warning.only_add_own_account: 你在使用自己的 %{app_name} 账户
-doc_auth.hybrid_flow_warning.only_add_phone_verify: 你要求 %{app_name} 使用你的电话来验证你的身份证件。
-doc_auth.hybrid_flow_warning.only_add_sp_services_html: 你在试图访问 %{service_provider_name} 服务。
-doc_auth.info.add_id_consent_with_phone: 仅在你已请求%{app_name}使用你的电话来验证你的身份的情况下才添加你的身份证件。
doc_auth.info.address: 如果你的居住地址和邮寄地址不同,也可以尝试验证你的邮寄地址。
doc_auth.info.address_guidance_puerto_rico_html: 波多黎各居民:
编辑你的地址,在地址第 2 行列出你的 urbanization 或 condominium。
doc_auth.info.capture_status_big_document: 太近了
@@ -678,8 +676,7 @@ doc_auth.info.learn_more: 对于我们如何保护你的敏感信息获得更多
doc_auth.info.lets_go: 身份验证包括两部分:
doc_auth.info.link_sent: 请查看你的手机并按照说明拍一张你身份证件的照片。
doc_auth.info.link_sent_complete_no_polling: 照好以后,在这里点击“继续”,完成验证身份。
-doc_auth.info.link_sent_complete_polling: 下一步会自动加载。
-doc_auth.info.login_access_sp: 你在使用%{app_name}访问 %{sp_name}。
+doc_auth.info.link_sent_complete_polling: 你在手机上验证身份后,下一步将会自动加载。
doc_auth.info.mailing_address: 我们会将包含验证码的信件邮寄到这个地址。
doc_auth.info.no_ssn: 你必须有社会保障号码才能完成身份验证。
doc_auth.info.passport_capture: 拍摄一张你护照本的数据页的照片。数据页上有你的护照照片和个人信息。
diff --git a/docs/attempts-api/schemas/events/IdentityProofingEvents.yml b/docs/attempts-api/schemas/events/IdentityProofingEvents.yml
index eb7a035212a..b27d98593c8 100644
--- a/docs/attempts-api/schemas/events/IdentityProofingEvents.yml
+++ b/docs/attempts-api/schemas/events/IdentityProofingEvents.yml
@@ -1,31 +1,31 @@
properties:
idv-address-submitted:
- $ref: "./identity-proofing/IdvAddressSubmitted.yml"
+ $ref: './identity-proofing/IdvAddressSubmitted.yml'
idv-document-uploaded:
- $ref: "./identity-proofing/IdvDocumentUploaded.yml"
+ $ref: './identity-proofing/IdvDocumentUploaded.yml'
idv-document-upload-submitted:
- $ref: "./identity-proofing/IdvDocumentUploadSubmitted.yml"
+ $ref: './identity-proofing/IdvDocumentUploadSubmitted.yml'
idv-enrollment-complete:
- $ref: "./identity-proofing/IdvEnrollmentComplete.yml"
+ $ref: './identity-proofing/IdvEnrollmentComplete.yml'
idv-ipp-ready-to-verify-visit:
- $ref: "./identity-proofing/IdvIppReadyToVerifyVisit.yml"
+ $ref: './identity-proofing/IdvIppReadyToVerifyVisit.yml'
idv-phone-otp-sent:
- $ref: "./identity-proofing/IdvPhoneOtpSent.yml"
+ $ref: './identity-proofing/IdvPhoneOtpSent.yml'
idv-phone-otp-submitted:
- $ref: "./identity-proofing/IdvPhoneOtpSubmitted.yml"
+ $ref: './identity-proofing/IdvPhoneOtpSubmitted.yml'
idv-phone-submitted:
- $ref: "./identity-proofing/IdvPhoneSubmitted.yml"
+ $ref: './identity-proofing/IdvPhoneSubmitted.yml'
idv-rate-limited:
- $ref: "./identity-proofing/IdvRateLimited.yml"
+ $ref: './identity-proofing/IdvRateLimited.yml'
idv-reproof:
- $ref: "./identity-proofing/IdvReproof.yml"
+ $ref: './identity-proofing/IdvReproof.yml'
idv-ssn-submitted:
- $ref: "./identity-proofing/IdvSsnSubmitted.yml"
+ $ref: './identity-proofing/IdvSsnSubmitted.yml'
idv-device-risk-assessment:
- $ref: "./identity-proofing/IdvDeviceRiskAssessment.yml"
+ $ref: './identity-proofing/IdvDeviceRiskAssessment.yml'
idv-verification-submitted:
- $ref: "./identity-proofing/IdvVerificationSubmitted.yml"
+ $ref: './identity-proofing/IdvVerificationSubmitted.yml'
idv-verify-by-mail-letter-requested:
- $ref: "./identity-proofing/IdvVerifyByMailLetterRequested.yml"
+ $ref: './identity-proofing/IdvVerifyByMailLetterRequested.yml'
idv-verify-by-mail-enter-code-submitted:
- $ref: "./identity-proofing/IdvVerifyByMailEnterCodeSubmitted.yml"
+ $ref: './identity-proofing/IdvVerifyByMailEnterCodeSubmitted.yml'
diff --git a/docs/attempts-api/schemas/events/identity-proofing/IdvDeviceRiskAssessment.yml b/docs/attempts-api/schemas/events/identity-proofing/IdvDeviceRiskAssessment.yml
index 0f47b501cd7..34b3373c9b1 100644
--- a/docs/attempts-api/schemas/events/identity-proofing/IdvDeviceRiskAssessment.yml
+++ b/docs/attempts-api/schemas/events/identity-proofing/IdvDeviceRiskAssessment.yml
@@ -1,7 +1,7 @@
description: |
This event captures the result of the Device Risk Assessment during Identity Verification.
allOf:
- - $ref: "../shared/EventProperties.yml"
+ - $ref: '../shared/EventProperties.yml'
- type: object
properties:
failure_reason:
diff --git a/docs/attempts-api/schemas/events/identity-proofing/IdvImageRetrievalFailed.yml b/docs/attempts-api/schemas/events/identity-proofing/IdvImageRetrievalFailed.yml
index 7c7754e9414..40d412eded3 100644
--- a/docs/attempts-api/schemas/events/identity-proofing/IdvImageRetrievalFailed.yml
+++ b/docs/attempts-api/schemas/events/identity-proofing/IdvImageRetrievalFailed.yml
@@ -3,18 +3,18 @@ description: |
Therefore, document upload failed.
These image file names and encryption keys are invalid, and are not saved in the document escrow.
allOf:
- - $ref: "../shared/EventProperties.yml"
+ - $ref: '../shared/EventProperties.yml'
- type: object
properties:
document_front_image_file_id:
type: string
- description: If this image existed, the ID generated for storage
+ description: If this image existed, the ID generated for storage
document_back_image_file_id:
type: string
- description: If this image existed, the ID generated for storage
+ description: If this image existed, the ID generated for storage
document_selfie_image_file_id:
type: string
- description: If this image existed, the ID generated for storage
+ description: If this image existed, the ID generated for storage
document_front_image_encryption_key:
type: string
description: Randomly generated Base64-encoded key generated to encrypt the front image file if it exists.
diff --git a/docs/attempts-api/schemas/events/identity-proofing/IdvVerificationSubmitted.yml b/docs/attempts-api/schemas/events/identity-proofing/IdvVerificationSubmitted.yml
index 3e72120bff1..f5fa2787cd9 100644
--- a/docs/attempts-api/schemas/events/identity-proofing/IdvVerificationSubmitted.yml
+++ b/docs/attempts-api/schemas/events/identity-proofing/IdvVerificationSubmitted.yml
@@ -1,7 +1,7 @@
description: |
When the user verifies their information when identity proofing.
allOf:
- - $ref: "../shared/EventProperties.yml"
+ - $ref: '../shared/EventProperties.yml'
- type: object
properties:
document_state:
diff --git a/docs/attempts-api/schemas/events/shared/EventProperties.yml b/docs/attempts-api/schemas/events/shared/EventProperties.yml
index f7421a7f8ba..80d61a0b346 100644
--- a/docs/attempts-api/schemas/events/shared/EventProperties.yml
+++ b/docs/attempts-api/schemas/events/shared/EventProperties.yml
@@ -25,7 +25,7 @@ properties:
format: float64
description: The time when the event occurred.
subject:
- $ref: "./Subject.yml"
+ $ref: './Subject.yml'
useragent_string:
type: string
description: The end user's browser's useragent string, which identifies the type of browser, device and operating system being used as well as the version of the browser.
diff --git a/lib/identity_config.rb b/lib/identity_config.rb
index 86ce3f187c5..f08e2c92807 100644
--- a/lib/identity_config.rb
+++ b/lib/identity_config.rb
@@ -127,8 +127,6 @@ def self.store
config.add(:doc_auth_error_glare_threshold, type: :integer)
config.add(:doc_auth_error_sharpness_threshold, type: :integer)
config.add(:doc_auth_max_attempts, type: :integer)
- config.add(:doc_auth_manual_upload_disabled_a_b_testing_enabled, type: :boolean)
- config.add(:doc_auth_manual_upload_disabled_a_b_testing_percent, type: :integer)
config.add(:doc_auth_max_capture_attempts_before_native_camera, type: :integer)
config.add(:doc_auth_max_submission_attempts_before_native_camera, type: :integer)
config.add(:doc_auth_passports_enabled, type: :boolean)
diff --git a/lib/reporting/api_transaction_count_report.rb b/lib/reporting/api_transaction_count_report.rb
index 97ce97f5491..d0eae77b872 100644
--- a/lib/reporting/api_transaction_count_report.rb
+++ b/lib/reporting/api_transaction_count_report.rb
@@ -21,8 +21,8 @@ def initialize(
time_range:,
verbose: false,
progress: false,
- slice: 6.hours,
- threads: 1
+ slice: 1.day,
+ threads: 5
)
@time_range = time_range
@verbose = verbose
@@ -76,7 +76,8 @@ def api_transaction_count
'Socure (KYC) - Shadow',
'Socure (KYC) - Non-Shadow',
'Fraud Score and Attribute',
- 'Threat Metrix',
+ 'Threat Metrix (IDV)',
+ 'Threat Metrix (Auth Only)',
],
[
"#{ time_range.begin.to_date} - #{time_range.end.to_date}",
@@ -84,10 +85,11 @@ def api_transaction_count
instant_verify_table.first,
phone_finder_table.first,
socure_table.first,
- socure_kyc_non_shadow_table.first,
socure_kyc_shadow_table.first,
+ socure_kyc_non_shadow_table.first,
fraud_score_and_attribute_table.first,
- threat_metrix_table.first,
+ threat_metrix_idv_table.first,
+ threat_metrix_auth_only_table.first,
],
]
end
@@ -138,8 +140,14 @@ def instant_verify_table
[instant_verify_table_count, result]
end
- def threat_metrix_table
- result = fetch_results(query: threat_metrix_query)
+ def threat_metrix_idv_table
+ result = fetch_results(query: threat_metrix_idv_query)
+ threat_metrix_table_count = result.count
+ [threat_metrix_table_count, result]
+ end
+
+ def threat_metrix_auth_only_table
+ result = fetch_results(query: threat_metrix_auth_only_query)
threat_metrix_table_count = result.count
[threat_metrix_table_count, result]
end
@@ -200,6 +208,7 @@ def true_id_query
properties.event_properties.vendor as vendor
| display uuid, id, timestamp, sp, dol_state, success,
billed, vendor, product_status, transaction_status, conversation_id, request_id, referenceID, decision_status, submit_attempts, remaining_submit_attempts
+ | limit 10000
QUERY
end
@@ -221,6 +230,7 @@ def phone_finder_query
| display uuid, id, timestamp, sp, dol_state, success,
phoneFinder_referenceID, phoneFinder_transactionID, phoneFinder_pass,
coalesce(temp_checks,"passed_all","") as phoneFinder_checks
+ | limit 10000
QUERY
end
@@ -236,6 +246,7 @@ def socure_query
properties.event_properties.reference_id as reference_id, properties.event_properties.submit_attempts as submit_attempts,
replace(replace(strcontains(name, "front"),"1","front"),"0","back") as side
| display uuid, id, timestamp, sp, dol_state, success, decision_result, side, docv_transaction_token, reference_id, submit_attempts
+ | limit 10000
QUERY
end
@@ -271,19 +282,29 @@ def instant_verify_query
resolution_transactionID,
resolution_success,
resolution_timed_out_flag
+ | limit 10000
QUERY
end
- def threat_metrix_query
+ def threat_metrix_idv_query
<<~QUERY
filter name = "IdV: doc auth verify proofing results"
| fields
properties.user_id as uuid,
@timestamp as timestamp,
properties.event_properties.proofing_results.context.stages.threatmetrix.success as tmx_success
-
| stats max(tmx_success) as max_tmx_success by uuid
-
+ | limit 10000
+ QUERY
+ end
+
+ def threat_metrix_auth_only_query
+ <<~QUERY
+ filter name = "account_creation_tmx_result"
+ | fields
+ properties.user_id as uuid,
+ @timestamp as timestamp,
+ | limit 10000
QUERY
end
@@ -301,6 +322,7 @@ def fraud_score_and_attribute_query
properties.event_properties.response_body.fraudpoint.vulnerable_victim_index as vulnerable_victim_index,
properties.event_properties.response_body.fraudpoint.risk_indicators_codes as risk_indicators_codes,
properties.event_properties.response_body.fraudpoint.risk_indicators_descriptions as risk_indicators_descriptions
+ | limit 10000
QUERY
end
@@ -324,7 +346,7 @@ def socure_kyc_shadow_query
properties.event_properties.socure_result.errors.I919 as I919,
properties.event_properties.socure_result.errors.R354 as R354
| filter name = "idv_socure_shadow_mode_proofing_result"
- | stats count(*) as c
+ | limit 10000
QUERY
end
@@ -334,7 +356,7 @@ def socure_kyc_non_shadow_query
| filter name='IdV: doc auth verify proofing results'
and properties.event_properties.proofing_results.context.stages.resolution.vendor_name='socure_kyc'
| sort @timestamp desc
- | stats count(*) as c
+ | limit 10000
QUERY
end
end
diff --git a/lib/reporting/irs_verification_demographics_report.rb b/lib/reporting/irs_verification_demographics_report.rb
new file mode 100644
index 00000000000..656a836ed14
--- /dev/null
+++ b/lib/reporting/irs_verification_demographics_report.rb
@@ -0,0 +1,231 @@
+# frozen_string_literal: true
+
+require 'csv'
+begin
+ require 'reporting/cloudwatch_client'
+ require 'reporting/cloudwatch_query_quoting'
+ require 'reporting/command_line_options'
+rescue LoadError => e
+ warn 'could not load paths, try running with "bundle exec rails runner"'
+ raise e
+end
+
+module Reporting
+ class IrsVerificationDemographicsReport
+ include Reporting::CloudwatchQueryQuoting
+
+ attr_reader :issuers, :time_range
+
+ module Events
+ IDV_DOC_AUTH_PROOFING_RESULTS = 'IdV: doc auth verify proofing results'
+ SP_REDIRECT_INITIATED = 'SP redirect initiated'
+
+ def self.all_events
+ constants.map { |c| const_get(c) }
+ end
+ end
+
+ # @param [Array] issuers
+ # @param [Range