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
-
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
-
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
-
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
-
Reset all role profile foreign keys on onboarding role changes before setting the active one.
-
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
-
Allow consultant profile updates to change domainId and subDomainIds, or deliberately document that they are immutable and provide an alternate migration path.
Flutter app
-
Add a consultant verification step or an immediate post-onboarding verification task flow.
-
Extend onboarding state/request models to include:
- verification LinkedIn URL
- verification notes
- verification documents
-
Add a verification/status section in profile/settings with:
- current status badge
- review feedback
- document list
- submit/resubmit actions
-
Fix consultant onboarding validation so the screen's required fields match the actual submission gate.
-
Correct availability/discoverability copy to reflect the true gating rules.
-
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.
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:
isVerifiedScope reviewed
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-155lib/data/models/onboarding/onboarding_request_model.dart:24-100The Dart Frog onboarding route also only accepts
role,personalInfo,consultantProfile,consulteeProfile, andagreement:backend/routes/api/onboarding/submit.dart:14-38backend/routes/api/onboarding/submit.dart:61-127The web flow does materially more. It has a dedicated
ConsultantVerificationFormthat 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-235Then the web server consumes
verificationLinkedinUrl,verificationNotes, andverificationDocuments, creates aconsultantProfileVerification, links documents, updatesverificationStatus, and notifies admins:/Users/kaustavghosh/Desktop/familiarise_web/utils/onboarding-server.ts:455-564Impact:
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-143But
ConsultantProfileData.isValidonly checksdomainId:lib/domain/entities/onboarding/consultant_profile_data.dart:58-60And the backend route only enforces presence of
domainIdand agreement acceptance:backend/routes/api/onboarding/submit.dart:77-127That means a consultant can submit onboarding with:
sessionTypessubDomainIdscareerStage/budgetPreference/preferredCommunicationMethodstring valuesThe 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-387Impact:
3. Availability step messaging is incorrect and misleading about discoverability
The consultant availability screen tells users:
Source:
lib/features/onboarding/screens/steps/availability_info_step.dart:149-165But consultant discovery in the mobile backend filters by
isVerified: true, not "has slots":backend/lib/database/repositories/consultant_explore_repository.dart:22-31backend/routes/api/consultants/index.dart:9-67And the mobile onboarding flow never creates a verification request or moves the consultant to
UNDER_REVIEW:backend/routes/api/onboarding/submit.dart:223-281By 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-524Impact:
4. The mobile repo has no consultant-side verification lifecycle after onboarding
The Dart Frog API surface under
backend/routes/apicurrently includes:/api/onboarding/submit/api/consultant/profile/api/consultee/profile/api/upload/imageThere is no equivalent to the web routes:
/api/verification/status/api/verification/submit/api/verification/documents/api/verification/resubmitReference 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-125The 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-350The 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-220Impact:
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:
consultantProfile.isVerifiedverificationStatusReference:
/Users/kaustavghosh/Desktop/familiarise_web/app/api/admin/verification/[verificationId]/route.ts:18-242This 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:
Assumption:
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-187By 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-423This means if a user ever re-runs onboarding or changes role, they can retain stale links such as:
consultantProfileIdfrom a previous consultant onboardingconsulteeProfileIdfrom a previous consultee onboardingImpact:
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-387lib/features/profile/screens/edit_profile_screen.dart:428-473The generic user update repository only writes non-null values:
backend/lib/database/repositories/user_repository.dart:73-110The consultee and consultant repositories do the same:
backend/lib/database/repositories/consultee_profile_repository.dart:80-108backend/lib/database/repositories/consultant_profile_repository.dart:59-76The consultant route also only updates subdomains when the new list is non-empty:
backend/routes/api/consultant/profile.dart:120-128So on mobile a user can add data, but often cannot remove it:
biolinkedinUrlwebsiteUrl/twitterUrl/githubUrl/videoIntroUrlaboutMelanguages,toolsAndTechnologies,sessionTypesThis is especially harmful in a verification workflow where users need to correct or remove rejected information.
Impact:
8. Mobile consultant profile editing cannot change primary domain or specializations
The mobile consultant edit flow does not build or send
domainIdorsubDomainIdsat all:lib/features/profile/screens/edit_profile_screen.dart:428-450And the Dart Frog consultant patch route hardcodes the existing
domainIdfrom the current profile instead of accepting a new one:backend/routes/api/consultant/profile.dart:98-118The onboarding flow does support domain + subdomain selection, but the ongoing profile management flow does not.
Impact:
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-185But 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:
Proposed fixes
Backend
Add a first-class consultant verification contract to Dart Frog:
GET /api/verification/statusPOST /api/verification/submitPOST/DELETE /api/verification/documentsPOST /api/verification/resubmitDecide explicitly whether Dart Frog is authoritative for consultant onboarding:
Strengthen onboarding validation:
subDomainIdsfor the selected domainReset all role profile foreign keys on onboarding role changes before setting the active one.
Redesign PATCH semantics for user/consultant/consultee profile updates:
Allow consultant profile updates to change
domainIdandsubDomainIds, or deliberately document that they are immutable and provide an alternate migration path.Flutter app
Add a consultant verification step or an immediate post-onboarding verification task flow.
Extend onboarding state/request models to include:
Add a verification/status section in profile/settings with:
Fix consultant onboarding validation so the screen's required fields match the actual submission gate.
Correct availability/discoverability copy to reflect the true gating rules.
Update edit-profile UX to support clearing/removing values rather than only additive edits.
Acceptance criteria
Regression test matrix
Onboarding
Verification lifecycle
REJECTEDEditing
bio,linkedinUrl,websiteUrl,githubUrl, etc actually clears DB statelanguages,toolsAndTechnologies,sessionTypes,skillsToDevelop) persists empty arraysDiscovery
Notes