fix(onboarding): hydrate authStore on signup + cover OAuth InsertWithTx - #12
Merged
Conversation
Three real fixes verified by running the registration flow end-to-end
in a browser (Playwright + docker-built backend):
1. sign-up-form.tsx — after register() succeeds, call handleLoginSuccess
to fetch /api/user/self and write the user into the authStore before
navigating to /welcome. Previously we just called navigate('/welcome'),
but /welcome's user guard reads from authStore (not the backend session
cookie) and bounced us straight to /sign-in. This is the root cause of
"我注册的时候没有触发onboarding啊" — the redirect happened so fast
it looked like onboarding never opened.
2. model/user.go InsertWithTx — same persona="unset" seed as Insert(),
for controller/oauth.go::OAuthBind which uses the transactional
variant. Previous fix only covered Insert(); OAuth users created via
the generic /api/oauth/* endpoints would still skip the wizard.
3. Dockerfile.dev — drop the COPY of LICENSE/NOTICE/THIRD-PARTY-LICENSES.md
into /licenses/. Those files don't exist in this fork, so the dev
image build failed at stage-1 step 4 — blocking any local rebuild of
the backend after Go code changes.
Verification:
- docker compose -f docker-compose.dev.yml -p deeprouter up --build (✅)
- POST /api/user/register with empty body → DB row has persona="unset" (✅)
- POST /api/user/register with persona/brand/client → DB has all fields
+ onboarding_completed_at stamped (✅)
- Browser: /sign-up → submit → /welcome wizard renders with trial credit
banner, 3-persona picker, Step 1 of 3 (✅)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… partial PATCH + step URLs
End-to-end test of the wizard exposed three more bugs the previous PRs missed:
1. controller.UpdateUserSetting only knew about notify_type / webhook / bark /
gotify. The frontend wizard sends persona / brand_preference /
preferred_client / sidebar_modules, but the handler:
a) Returned MsgSettingInvalidType ("Invalid warning type") because
notify_type was empty — this is the toast the user kept seeing.
b) Built dto.UserSetting{} from scratch, wiping persona/brand/client
even when validation passed.
Reworked as a real partial-update endpoint:
- notify_type validation block runs only when notify_type is non-empty
(treats empty as "not updating notify config")
- settings = existingSettings, then override only fields the caller
provided (pointer fields for B2C, gate-by-isNotifyUpdate for the
notify cluster)
- Notify-channel reset moved inside the gate so switching from
webhook → bark still clears stale webhook URL.
2. Welcome wizard: default-select Casual so Continue is enabled on landing.
Non-technical users had to discover that they had to click the card
before they could move on.
3. ChoiceCard description had `line-clamp-2` — Team / Enterprise card was
cut at "team-only tools coming soon" + ellipsis. Removed the clamp;
each step now shows the full description.
4. Each wizard step has its own URL via ?step=persona|brand|client search
param. Browser back/forward works correctly, deep-links land on the
right step, Back button rewinds. Deep-link guard: ?step=brand without
a persona pick rewinds to ?step=persona.
Verified end-to-end:
- POST /api/user/register → /welcome (default Casual selected)
- /welcome?step=brand → pick Claude → /welcome?step=client
- /welcome?step=client → Cherry Studio auto-selected → Finish
- DB: persona=casual, preferred_client=cherry-studio, sidebar_modules
swapped to casual preset, acquisition_channel/timezone preserved
- Browser navigated to /onboarding/cherry-studio (no longer silently fails)
- No more "Invalid warning type" toast on the Finish click
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This is the actually-tested fix for "我注册的时候没有触发onboarding". PR #11 fixed two real bugs (Setting type mismatch, OAuth seed in Insert) but missed three more that I only caught by running the flow end-to-end:
Verified
```
✅ docker compose -f docker-compose.dev.yml -p deeprouter up --build
✅ POST /api/user/register {} → DB has persona="unset"
✅ POST /api/user/register {persona,brand,client} → DB has all 3 + onboarding_completed_at
✅ Browser: /sign-up → submit → /welcome (NOT /sign-in)
✅ /welcome renders: 👋 banner, ¥1.00 trial credit (≈200 chats), 3-persona picker, Step 1 of 3
```
What CI didn't catch (so we know to fix this separately)
That's why PR #8's `cleanUser.Setting = &settingStr` (`*string` to `string`) silently merged. CI scope expansion is out of scope for this PR but worth tracking.
Test plan
🤖 Generated with Claude Code