Skip to content

CCCT-2790 Add Journey-Aware Analytics To Backup Code And Email Flows - #3958

Open
Jignesh-dimagi wants to merge 8 commits into
commcare_2.65from
ccct-2790-analytics-backupcode-email-recovery-2.65
Open

Jignesh-dimagi wants to merge 8 commits into
commcare_2.65from
ccct-2790-analytics-backupcode-email-recovery-2.65

Conversation

@Jignesh-dimagi

@Jignesh-dimagi Jignesh-dimagi commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

CCCT-2790

Technical Summary

The backup code and email screens are shared across many journeys, so a screen-level event would have recorded what the user saw without recording why they were there — a confirm-code screen looks identical whether the user is changing their code, recovering access after forgetting it, or authorising an email change. Every step therefore reports one event, personalid_account_security_action, carrying a workflow param naming the journey and an event_type param naming the step, so a single funnel can be read end to end per journey rather than as a pile of anonymous screen views. Where a screen is genuinely shared, the journey is passed in as a nav argument rather than inferred, because the existing EmailWorkFlow enum describes which recovery route is available, not why the user arrived. Anything presented as a dialog reports to the existing user_prompt event instead, keeping prompts in one place alongside the email reminders, and a new shown action gives those prompts a denominator so accept and skip read as rates rather than raw counts. outcome, failed_attempts and reason are attached only to the steps where they mean something, making dropoff and lockout visible per journey. The net addition is one event and three param values — not one event per flow.

Safety Assurance

Safety story

What gives confidence

  • I installed the build on a device and exercised every flow.
  • Analytics-only; the sole behaviour change is one required nav argument.

Risks to review

  • Safe Args made backupCodeWorkflow required, breaking four test files; commit 6 repairs them.
  • Shared base screens mean registration and recovery now emit this event too.

Automated test coverage

No new tests. The 174 existing tests across 15 PersonalID screen classes pass.

🤖 Generated with Claude Code

Jignesh-dimagi and others added 5 commits October 8, 2026 17:25
One event covers the backup-code and email journeys, with workflow and
event_type params separating them, mirroring how otp_requested already
handles the same problem. Only the event name is new; every param constant
already existed.

Nothing reports it yet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reports the confirm-code screen, its attempts and lockout, the forgot-code
tap, the set-new-code screen and its outcome. The abandon dialog goes to
user_prompt, matching how the app already reports prompts.

The confirm and set-new-code screens are shared by several journeys, and
their existing arguments cannot say which one the user is in - emailWorkflow
carries the forgot route available, not the reason for being there. So
BackupCodeWorkflow, until now unused, becomes a nav argument that each entry
point sets explicitly.

The set-new-code base class spans two nav graphs, so it takes the workflow
through an abstract method rather than Safe Args.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Covers the three recovery journeys - account configuration, existing user
and pending backup code - which share the same email screens and are told
apart by the workflow param.

Only the navigation and limit moments are added. Sending and verifying the
email OTP already report through otp_requested in EmailHelper, so repeating
them here would give two sources for the same action.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both reminder dialogs report their button taps through user_prompt, matching
how the app already reports prompts, with the info param separating them.
The code confirmation itself carries an outcome and an attempt count, which
user_prompt has no params for, so it goes to the account security event and
stays comparable with the same step in the other flows.

The Forgot tap is reported from the click listener rather than inside
onForgotClicked, which also runs automatically on lockout and would
otherwise inflate the count.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both email-change routes converge on the shared email screens carrying
EmailWorkFlow.EXISTING_USER, so those screens cannot tell which auth step
the user came through. EXISTING_USER now maps to a neutral email_change
workflow, and the two route-specific workflows are emitted only from the
auth steps, where the route is known.

email_changed goes on the account security event rather than
personalid_manage_profile_action, keeping the multi-screen funnel in one
table.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Jignesh-dimagi Jignesh-dimagi self-assigned this Oct 8, 2026
@Jignesh-dimagi

Jignesh-dimagi commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor Author

Suggested Review Order

The six commits tell this in order — reading commit-by-commit is easier than file-by-file:

  • 7a19cd08d — the event, its params and every value they can take
  • 056365989 — change backup code; introduces the nav argument that carries the journey
  • f34bd15ac — the three recovery routes
  • 0e791d33c — periodic reminders, reported as user_prompt
  • 574aac354 — email change; remaps EXISTING_USER, so commit 1's mapper reads oddly until here
  • f96d5c14b — test call sites for the required nav argument

@Jignesh-dimagi Jignesh-dimagi added the skip-integration-tests Skip android tests. label Oct 8, 2026
@Jignesh-dimagi
Jignesh-dimagi requested review from a team and OrangeAndGreen and removed request for a team October 8, 2026 12:07
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d1ec2dc2-4f3d-418a-ba44-027c7e4e9e27
📥 Commits

Reviewing files that changed from the base of the PR and between 861d0bb and aedf7b7.

📒 Files selected for processing (25)
  • app/res/navigation/nav_graph_personalid_profile.xml
  • app/src/org/commcare/fragments/personalId/BackupCodeWorkflow.kt
  • app/src/org/commcare/fragments/personalId/BasePersonalIdEmailVerificationFragment.kt
  • app/src/org/commcare/fragments/personalId/BasePersonalIdPhoneVerificationFragment.kt
  • app/src/org/commcare/fragments/personalId/BasePersonalIdSendEmailOtpFragment.kt
  • app/src/org/commcare/fragments/personalId/PersonalIdAccountConfigSetNewBackupCodeFragment.kt
  • app/src/org/commcare/fragments/personalId/PersonalIdBackupCodeFragment.kt
  • app/src/org/commcare/fragments/personalId/PersonalIdEmailVerificationForgotBackupCodeFragment.kt
  • app/src/org/commcare/fragments/personalId/PersonalIdProfileEmailVerificationFragment.kt
  • app/src/org/commcare/fragments/personalId/PersonalIdProfileSendEmailOtpFragment.kt
  • app/src/org/commcare/google/services/analytics/AnalyticsParamValue.java
  • app/src/org/commcare/google/services/analytics/CCAnalyticsEvent.java
  • app/src/org/commcare/google/services/analytics/FirebaseAnalyticsUtil.java
  • app/src/org/commcare/personalId/BackupCodeReminderDialog.kt
  • app/src/org/commcare/personalId/profile/BasePersonalIdSetNewBackupCodeFragment.kt
  • app/src/org/commcare/personalId/profile/PersonalIdProfileBackupCodeFragment.kt
  • app/src/org/commcare/personalId/profile/PersonalIdProfileEditFragment.kt
  • app/src/org/commcare/personalId/profile/PersonalIdProfileFragment.kt
  • app/src/org/commcare/personalId/profile/PersonalIdProfilePhoneVerificationFragment.kt
  • app/src/org/commcare/personalId/profile/PersonalIdProfileSetNewBackupCodeFragment.kt
  • app/src/org/commcare/utils/AccountSecurityAnalyticsMapper.kt
  • app/unit-tests/src/org/commcare/personalId/profile/BasePersonalIdSetNewBackupCodeFragmentTest.kt
  • app/unit-tests/src/org/commcare/personalId/profile/PersonalIdProfileBackupCodeChangeEmailFragmentTest.kt
  • app/unit-tests/src/org/commcare/personalId/profile/PersonalIdProfileBackupCodeFragmentTest.kt
  • app/unit-tests/src/org/commcare/personalId/profile/PersonalIdProfilePhoneVerificationFragmentTest.kt

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The change adds account-security analytics for backup-code prompts, confirmation and setup, and email and phone verification. Backup-code workflow arguments now identify the journey through navigation and support workflow-specific analytics. Related tests now provide these arguments.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant PersonalIdProfileBackupCodeFragment
  participant AccountSecurityAnalyticsMapper
  participant FirebaseAnalyticsUtil
  participant FirebaseAnalytics

  User->>PersonalIdProfileBackupCodeFragment: Submit backup code
  PersonalIdProfileBackupCodeFragment->>AccountSecurityAnalyticsMapper: Map BackupCodeWorkflow
  AccountSecurityAnalyticsMapper-->>PersonalIdProfileBackupCodeFragment: Analytics workflow
  PersonalIdProfileBackupCodeFragment->>FirebaseAnalyticsUtil: Report confirmation outcome and attempt count
  FirebaseAnalyticsUtil->>FirebaseAnalytics: Log account-security event
Loading

Suggested reviewers: shubham1g5

Merge Risk: ⚪ Minimal · up to aedf7

No actionable merge-blocking issue was identified. The inspected backup-code navigation routes provide the required workflow argument.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.45% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 62 functions across 24 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the main change: journey-aware analytics for backup-code and email flows.
Description check ✅ Passed The description includes the ticket link, technical rationale, safety story, behavior impact, and automated test coverage. It omits the optional Product Description and the Labels and Review checklist…
Full details: Docstring Coverage

Explanation

Docstring coverage is 6.45% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 62 functions across 24 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

❤️ Share

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

The backupCodeWorkflow argument is required, so Safe Args stopped
generating the single-argument builders these tests used. Each call site
now passes what its real counterpart passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Jignesh-dimagi
Jignesh-dimagi force-pushed the ccct-2790-analytics-backupcode-email-recovery-2.65 branch from aedf7b7 to f96d5c1 Compare October 8, 2026 13:09
@codecov

codecov Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 37.45%. Comparing base (f4b6c1b) to head (39a206f).
⚠️ Report is 7 commits behind head on commcare_2.65.

Additional details and impacted files
@@                 Coverage Diff                 @@
##             commcare_2.65    #3958      +/-   ##
===================================================
+ Coverage            37.32%   37.45%   +0.12%     
- Complexity            6864     6900      +36     
===================================================
  Files                 1034     1036       +2     
  Lines                61094    61585     +491     
  Branches              7472     7571      +99     
===================================================
+ Hits                 22802    23064     +262     
- Misses               35637    35825     +188     
- Partials              2655     2696      +41     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread app/src/org/commcare/utils/AccountSecurityAnalyticsMapper.kt Outdated

@OrangeAndGreen OrangeAndGreen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A couple suggestions but nothing I'd consider blocking

Jignesh-dimagi and others added 2 commits October 9, 2026 11:48
The forgot-backup-code verification screen serves both the forgot-code
and pending-code journeys, but hardcoded the former, so five of the
pending-code journey's events were landing in the forgot-code funnel.
The screen now takes the workflow as a nav argument and passes a matching
BackupCodeWorkflow on to set-new-code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
OtpAnalyticsMapper.workflowParam(EmailWorkFlow) has the same signature in
the same package, so the wrong import compiled silently. The two write the
same workflow param but deliberately different vocabularies: launch context
there, journey here. Renaming makes the choice explicit at each call site,
and the KDoc records why they are not joinable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-integration-tests Skip android tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants