Skip to content

ChatGPT 5.4: Onboarding and consultant verification lifecycle review: missing verification flow, weak validation, and profile-edit dead ends #62

@teetangh

Description

@teetangh

Onboarding and consultant verification lifecycle review: missing verification flow, weak validation, and profile-edit dead ends

Summary

The mobile repo currently lets a consultant complete onboarding, reach the dashboard, and edit basic profile fields, but it does not provide a complete consultant verification lifecycle.

Compared with the web repo, the Dart Frog backend and Flutter app are missing the routes, models, UI, validation, and moderation hooks that turn "consultant signed up" into "consultant submitted for review, received feedback, resubmitted, and became discoverable."

This is broader than a parity issue. There are several concrete lifecycle bugs:

  • consultants can finish onboarding without ever creating a verification request
  • the app tells consultants they become visible once they add slots, but discovery still filters on isVerified
  • mobile validation is weaker than both the UI copy and the web contract
  • profile editing is merge-only, so rejected/stale profile data often cannot be cleared
  • role/profile foreign keys are not reset when onboarding changes role

Scope reviewed

  • mobile Flutter onboarding flow
  • mobile Flutter profile/settings flow
  • Dart Frog onboarding/profile routes and repositories
  • consultant discovery gating in the mobile backend
  • web onboarding + consultant verification lifecycle used as the stronger reference implementation

Findings

1. Consultant onboarding completes without any verification submission surface

The Flutter onboarding flow has only six consultant steps: role, personal info, professional profile, availability info, agreement, review. There is no consultant verification step, no verification state in the onboarding state model, and no verification payload in the request model:

  • lib/features/onboarding/screens/onboarding_shell_screen.dart:111-155
  • lib/data/models/onboarding/onboarding_request_model.dart:24-100

The Dart Frog onboarding route also only accepts role, personalInfo, consultantProfile, consulteeProfile, and agreement:

  • backend/routes/api/onboarding/submit.dart:14-38
  • backend/routes/api/onboarding/submit.dart:61-127

The web flow does materially more. It has a dedicated ConsultantVerificationForm that requires a LinkedIn URL and at least one supporting document:

  • /Users/kaustavghosh/Desktop/familiarise_web/app/form/onboarding/components/ConsultantVerificationForm.tsx:15-120
  • /Users/kaustavghosh/Desktop/familiarise_web/app/form/onboarding/components/ConsultantVerificationForm.tsx:127-235

Then the web server consumes verificationLinkedinUrl, verificationNotes, and verificationDocuments, creates a consultantProfileVerification, links documents, updates verificationStatus, and notifies admins:

  • /Users/kaustavghosh/Desktop/familiarise_web/utils/onboarding-server.ts:455-564

Impact:

  • mobile consultant onboarding can report success while never entering the review queue
  • no verification documents or review notes exist to support later moderation
  • onboarding feels "complete" in app but is operationally incomplete

2. Consultant onboarding validation is weaker than both the UI copy and the web contract

The consultant onboarding screen labels headline and experience as required:

  • lib/features/onboarding/screens/steps/consultant_profile_step.dart:125-143

But ConsultantProfileData.isValid only checks domainId:

  • lib/domain/entities/onboarding/consultant_profile_data.dart:58-60

And the backend route only enforces presence of domainId and agreement acceptance:

  • backend/routes/api/onboarding/submit.dart:77-127

That means a consultant can submit onboarding with:

  • no headline
  • no experience
  • arbitrary sessionTypes
  • arbitrary subDomainIds
  • arbitrary careerStage / budgetPreference / preferredCommunicationMethod string values
  • invalid or non-existent related IDs unless the DB rejects them downstream

The web onboarding server validates the whole payload before writing and uses a stronger typed schema:

  • /Users/kaustavghosh/Desktop/familiarise_web/utils/onboarding-server.ts:368-387

Impact:

  • UI-required fields are not actually required
  • bad enum values and malformed profile state can leak into persistence
  • consultants can "pass" onboarding with a profile that is immediately unusable for verification or discovery

3. Availability step messaging is incorrect and misleading about discoverability

The consultant availability screen tells users:

"Your profile will be visible to potential mentees once you add at least one time slot."

Source:

  • lib/features/onboarding/screens/steps/availability_info_step.dart:149-165

But consultant discovery in the mobile backend filters by isVerified: true, not "has slots":

  • backend/lib/database/repositories/consultant_explore_repository.dart:22-31
  • backend/routes/api/consultants/index.dart:9-67

And the mobile onboarding flow never creates a verification request or moves the consultant to UNDER_REVIEW:

  • backend/routes/api/onboarding/submit.dart:223-281

By contrast, the web onboarding and verification flow explicitly treats verification as the gating step for visibility:

  • /Users/kaustavghosh/Desktop/familiarise_web/app/form/onboarding/components/ConsultantVerificationForm.tsx:216-230
  • /Users/kaustavghosh/Desktop/familiarise_web/utils/onboarding-server.ts:517-524

Impact:

  • consultants are given false expectations about when they will appear publicly
  • support burden increases because the app says "add slots" while the backend still requires verification
  • this is likely to be interpreted as a search/discovery bug by users

4. The mobile repo has no consultant-side verification lifecycle after onboarding

The Dart Frog API surface under backend/routes/api currently includes:

  • /api/onboarding/submit
  • /api/consultant/profile
  • /api/consultee/profile
  • /api/upload/image

There is no equivalent to the web routes:

  • /api/verification/status
  • /api/verification/submit
  • /api/verification/documents
  • /api/verification/resubmit

Reference implementations:

  • /Users/kaustavghosh/Desktop/familiarise_web/app/api/verification/status/route.ts:6-94
  • /Users/kaustavghosh/Desktop/familiarise_web/app/api/verification/submit/route.ts:6-117
  • /Users/kaustavghosh/Desktop/familiarise_web/app/api/verification/documents/route.ts:15-183
  • /Users/kaustavghosh/Desktop/familiarise_web/app/api/verification/resubmit/route.ts:1-125

The web settings page actively uses this contract to fetch rejection/needs-info feedback and resubmit verification:

  • /Users/kaustavghosh/Desktop/familiarise_web/app/dashboard/consultant/[consultantId]/(features)/settings/SettingsTab.tsx:158-193
  • /Users/kaustavghosh/Desktop/familiarise_web/app/dashboard/consultant/[consultantId]/(features)/settings/SettingsTab.tsx:293-350

The mobile app has no parallel UI surface. The profile screen only exposes generic settings like edit profile, bookings, notifications, support, password, sessions, delete account, and sign out:

  • lib/features/profile/screens/profile_screen.dart:65-220

Impact:

  • consultants cannot see current verification status in app
  • consultants cannot view rejection reasons / feedback details
  • consultants cannot upload verification documents from mobile
  • consultants cannot resubmit after rejection or needs-info states

5. The mobile backend cannot close the verification loop on its own

Even if a consultant somehow obtained a pending verification state externally, the mobile backend has no admin/staff moderation surface to review and transition it.

The web repo includes dedicated review routes that:

  • fetch verification details with consultant profile + documents
  • write review outcomes
  • update consultantProfile.isVerified
  • map review results to verificationStatus
  • attach per-document feedback
  • notify the consultant of the review result

Reference:

  • /Users/kaustavghosh/Desktop/familiarise_web/app/api/admin/verification/[verificationId]/route.ts:18-242

This matters if the Dart Frog backend is intended to be a self-sufficient backend for the mobile app's consultant lifecycle. Right now it is not.

Impact:

  • if the mobile backend is deployed independently, consultant verification cannot move from pending to reviewed
  • the consultant lifecycle depends on the web backend for the parts that matter most

Assumption:

  • if the product intentionally keeps admin/staff moderation web-only, the mobile backend still needs the consultant-side status/submit/document/resubmit surface and the mobile docs/UI should state clearly that review is web-managed

6. Onboarding role changes can leave stale profile foreign keys behind

The mobile onboarding write path updates the selected role and whichever profile ID is relevant, but it does not clear other role profile foreign keys first:

  • backend/lib/database/repositories/user_repository.dart:133-187

By contrast, the web onboarding server explicitly resets all profile foreign keys before writing the new role-specific ones:

  • /Users/kaustavghosh/Desktop/familiarise_web/utils/onboarding-server.ts:408-423

This means if a user ever re-runs onboarding or changes role, they can retain stale links such as:

  • consultantProfileId from a previous consultant onboarding
  • consulteeProfileId from a previous consultee onboarding

Impact:

  • mixed-role user state
  • authorization ambiguity in downstream code that assumes one active role profile
  • future bugs in booking, collaborator, or dashboard flows that key off profile IDs

7. Profile editing is merge-only, so users often cannot clear stale data

The Flutter edit-profile screen only sends non-empty fields:

  • lib/features/profile/screens/edit_profile_screen.dart:361-387
  • lib/features/profile/screens/edit_profile_screen.dart:428-473

The generic user update repository only writes non-null values:

  • backend/lib/database/repositories/user_repository.dart:73-110

The consultee and consultant repositories do the same:

  • backend/lib/database/repositories/consultee_profile_repository.dart:80-108
  • backend/lib/database/repositories/consultant_profile_repository.dart:59-76

The consultant route also only updates subdomains when the new list is non-empty:

  • backend/routes/api/consultant/profile.dart:120-128

So on mobile a user can add data, but often cannot remove it:

  • clear bio
  • clear linkedinUrl
  • clear websiteUrl / twitterUrl / githubUrl / videoIntroUrl
  • clear consultee aboutMe
  • clear languages, toolsAndTechnologies, sessionTypes
  • clear all consultant subdomains

This is especially harmful in a verification workflow where users need to correct or remove rejected information.

Impact:

  • stale profile data persists after edits
  • rejected consultants cannot fully address review feedback from mobile
  • app and backend silently disagree with user intent when a field is cleared in UI

8. Mobile consultant profile editing cannot change primary domain or specializations

The mobile consultant edit flow does not build or send domainId or subDomainIds at all:

  • lib/features/profile/screens/edit_profile_screen.dart:428-450

And the Dart Frog consultant patch route hardcodes the existing domainId from the current profile instead of accepting a new one:

  • backend/routes/api/consultant/profile.dart:98-118

The onboarding flow does support domain + subdomain selection, but the ongoing profile management flow does not.

Impact:

  • consultants cannot update their primary domain from mobile
  • consultants cannot correct specialization taxonomy after rejection or profile evolution
  • the mobile app has no route to keep consultant categorization aligned with the web directory

9. The onboarding/dashboard transition overstates completion for consultants

After successful submission, the mobile app immediately marks onboarding complete and sends the user to /dashboard:

  • lib/features/onboarding/screens/onboarding_shell_screen.dart:167-185

But for consultants there is no intervening verification step, no visible status page, no moderation queue submission, and no document submission. The result is a dashboard that looks like success while core consultant readiness work is still missing.

Impact:

  • consultant users get a false-positive completion experience
  • support/debugging becomes harder because "I finished onboarding" is technically true in app state but false in marketplace-readiness terms

Proposed fixes

Backend

  1. Add a first-class consultant verification contract to Dart Frog:

    • GET /api/verification/status
    • POST /api/verification/submit
    • POST/DELETE /api/verification/documents
    • POST /api/verification/resubmit
  2. Decide explicitly whether Dart Frog is authoritative for consultant onboarding:

    • if yes, add staff/admin review routes or a shared moderation service
    • if no, document the web dependency and keep the mobile consultant contract compatible with the web verification lifecycle
  3. Strengthen onboarding validation:

    • validate consultant required fields consistently with UI
    • validate enums and relation IDs
    • reject invalid subDomainIds for the selected domain
    • consider a typed validator layer similar to the web schema path
  4. Reset all role profile foreign keys on onboarding role changes before setting the active one.

  5. Redesign PATCH semantics for user/consultant/consultee profile updates:

    • distinguish omitted fields from explicit clears
    • support empty arrays for relation/list clearing
    • support nullable scalar clearing
  6. Allow consultant profile updates to change domainId and subDomainIds, or deliberately document that they are immutable and provide an alternate migration path.

Flutter app

  1. Add a consultant verification step or an immediate post-onboarding verification task flow.

  2. Extend onboarding state/request models to include:

    • verification LinkedIn URL
    • verification notes
    • verification documents
  3. Add a verification/status section in profile/settings with:

    • current status badge
    • review feedback
    • document list
    • submit/resubmit actions
  4. Fix consultant onboarding validation so the screen's required fields match the actual submission gate.

  5. Correct availability/discoverability copy to reflect the true gating rules.

  6. Update edit-profile UX to support clearing/removing values rather than only additive edits.

Acceptance criteria

  • consultant onboarding from mobile creates or updates a verification request when required
  • consultants can upload and remove verification documents from mobile
  • consultants can read current verification status and review feedback from mobile
  • rejected or needs-info consultants can resubmit from mobile
  • consultant onboarding cannot submit when required fields shown in UI are missing
  • profile copy does not claim slot creation alone makes a consultant discoverable
  • changing onboarding role does not leave stale role-profile foreign keys on the user
  • profile edits can explicitly clear nullable fields and empty relation/list fields
  • consultant domain and specialization edits are either supported or intentionally blocked with explicit product messaging

Regression test matrix

Onboarding

  • consultee onboarding still succeeds with valid data
  • consultant onboarding with missing headline/experience fails if UI marks them required
  • consultant onboarding with invalid domain/subdomain combination fails
  • consultant onboarding persists verification request and status transition
  • consultant onboarding without required verification materials fails if consultant verification is mandatory

Verification lifecycle

  • consultant can fetch verification status before any request
  • consultant can submit initial verification with LinkedIn URL + documents
  • consultant can resubmit after REJECTED
  • consultant cannot resubmit in invalid states
  • consultant can only view/manipulate their own verification artifacts

Editing

  • clearing bio, linkedinUrl, websiteUrl, githubUrl, etc actually clears DB state
  • clearing all consultant subdomains removes relation rows
  • clearing list fields (languages, toolsAndTechnologies, sessionTypes, skillsToDevelop) persists empty arrays
  • changing consultant domain updates dependent taxonomy safely

Discovery

  • unverified consultants do not appear in public consultant discovery
  • verification-approved consultants do appear once other discoverability requirements are satisfied
  • app copy and UI state match the real discoverability rules

Notes

  • This issue intentionally focuses on onboarding + consultant verification. Storage-specific concerns for document buckets, signed uploads, and cleanup are already captured in the storage/document bucket.
  • Auth/session concerns like sign-out not revoking the server session are already captured in the BetterAuth bucket.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions