Repository navigation
Commit b339465
fix(plugin-auth): Create User with no email names Email, and a wrong password on the password-change screen reads in the user's language (#28288)
domain:server#1 · os-elon-musk · session_016WV4cwXFwjU2YZW2dRuZZt
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DB7otGmwMKQJqKhPxGv4D83)_
Fixes #27857
Part of #27869
Clause-②: no
Metadata-protocol: none
Skills-docs: none — `git grep` of `skills/**` and `content/docs/**` for
"Either email or phoneNumber is required", "Invalid password" and
`INVALID_PASSWORD` has zero hits.
## 维护者速读
- 改了什么:设置 → 创建用户:不填邮箱时,报错从「Either email or phoneNumber is
required」改为「Email is required」(开启手机号登录时为「Email or phone number is
required」);强制改密页面输错当前/临时密码时,按用户语言显示提示,不再显示英文「Invalid password」。
- 为什么改:HotCRM 18.2.0 设置走查:报错点名了界面上不存在的
`phoneNumber`;法语用户改密输错时看到英文。邮箱必填标记另立卡(见下文)。
- 风险与回滚:错误码 `INVALID_REQUEST` 与状态 400 不变,只改措辞;`createAuthClient` 的
`changePassword` 抛错时保留 better-auth
的错误码(原先丢失,映射永不触发);界面只多一个翻译键;元数据未改。回滚即还原本 PR。
-
先看:`packages/plugins/plugin-auth/src/admin-user-endpoints.ts`(报错措辞)、`ui/packages/auth/src/createAuthClient.ts`(保留错误码)、`ui/packages/app-shell/src/console/RemediationOverlay.tsx`(错误码映射)、`ui/packages/i18n/src/locales/fr.ts`。
- 两分钟验证:设置 → 用户 → 创建用户,邮箱留空提交:提示「Email is
required」;以法语用户登录强制改密页,临时密码输错:显示法语提示。
- 需要你做的:无,席位落地。
## What changes
One commit per card, plus a revert commit, a merge of `origin/main`, and
the seat-review fix for #27869 (a):
1. **#27857 — Create User with no email.** `plugin-auth`
`admin-user-endpoints.ts`: with neither an email nor a phone number, the
refusal reads "Email is required", or "Email or phone number is
required" when phone sign-in is on (`deps.phoneNumberEnabled()`). It
used to read "Either email or phoneNumber is required", naming a body
key. Status 400 and code `INVALID_REQUEST` are unchanged (dispatch:
wording only).
2. **#27869 (a) — "Invalid password" on the password-change screen.**
better-auth's `/change-password` refuses a wrong current or temporary
password with `APIError.from('BAD_REQUEST',
BASE_ERROR_CODES.INVALID_PASSWORD)`, so the body is `{ message: "Invalid
password", code: "INVALID_PASSWORD" }` (better-auth 1.7.12,
`api/routes/update-user.mjs`). Two links were broken:
- `createAuthClient`'s `changePassword` threw `new Error(error.message)`
and dropped the code. It now throws through `toAuthError`, as sign-in
and the organization methods already do, so the thrown error carries
`code`. The message is unchanged.
- `ChangePasswordForm` in `RemediationOverlay.tsx` showed `err.message`
as it came. It now maps `INVALID_PASSWORD` to
`auth.remediation.password.wrongPassword`, a new key in all ten console
packs (ar, de, en, es, fr, ja, ko, pt, ru, zh). Any other refusal keeps
the server's message.
### What this PR does not carry
- **The Email required mark (#27857's dialog half).** The measured shape
was two visibility-gated Email params on the one field. It trips
`feature-gate-guard.test.ts`, whose registry is
`packages/spec/src/kernel/public-auth-features.ts`, outside this PR's
surface: the negated `phoneNumber` gate is not a shape `gatedInputs`
books, and both params resolve to one path. Seat ruling B: it was
committed (3a05184), then taken out again by the revert commit, and the
seat files it as its own card. #27857's refusal row still closes here,
as the seat ruled.
- **#27857's acceptance line "the refusal carries a code the console can
localise".** A new code is a `Clause-②: yes` change, and the dispatch
fixes the code as `INVALID_REQUEST`, so it is reported as a finding for
the seat.
- **#27869 stays open (`Part of`).** Its (b) and "loudly" halves are
#28107 and #28109. This PR leaves #27869 open; the seat shuts the card
once all its rows are carried.
## Tests
- New: `changePassword-code-27869.test.ts` (drives the real better-auth
client through a mocked `fetch`; a 400 `{ message: 'Invalid password',
code: 'INVALID_PASSWORD' }` from `/change-password` rejects with `.code
=== 'INVALID_PASSWORD'` and the message unchanged). New:
`RemediationOverlay.wrongPassword-27869.test.tsx` (the fr and en
sentences, plus a control: another code keeps the server message; it
mocks `useAuth`, so the client pin above covers the first link).
Extended: `admin-user-endpoints.test.ts` (the refusal wording with phone
sign-in off and on, code and status pinned). Updated:
`request-json-body-refusal.test.ts` (the empty-body control reads the
new wording).
- `pnpm --filter @objectstack/plugin-auth test`: Test Files 205 passed
(205), Tests 3917 passed, 10 skipped. `typecheck`: exit 0. `ui` vitest
over `packages/auth/`, `packages/app-shell/src/console/` and
`packages/i18n/`: Test Files 354 passed (354), Tests 3299 passed, 13
skipped. `@object-ui/auth` `type-check`: exit 0.
- Ablations (each through `scripts/ablation-replace.mjs`, restored to
the HEAD blob, `git status` clean after):
- Old refusal wording put back → `admin-user-endpoints.test.ts` 2 failed
/ 93 passed.
- The `INVALID_PASSWORD` mapping disabled →
`RemediationOverlay.wrongPassword-27869.test.tsx` 2 failed / 1 passed
(the control stays green).
- `changePassword` back to `throw new Error(error.message ?? …)` →
`changePassword-code-27869.test.ts` 1 failed (`expected undefined to be
'INVALID_PASSWORD'`).
## Acceptance notes
- The "code the console can localise" half of #27857 and the Email
required mark are in the card report as findings.
## Verification
The test and ablation readings above are on head `d5b0a9e4`. The gate
readings below are on `9248a860`; `d5b0a9e4` adds only the
`ui/packages/auth` commit, `dispatch-gates --commands` derives the same
66 families on it, and their rerun on `d5b0a9e4` is recorded in the card
report on #27857.
<details><summary>Derived gate families: 66 of 66 exit 0</summary>
- `node scripts/pm/dispatch-gates.mjs --commands` derived 66 families.
They ran after builds of `@objectstack/cli` + `platform-objects` (with
the i18n-bundle packages `check:i18n` names), the
`@objectstack/dogfood^...` and `@objectstack/runtime^...` closures, and
`@objectstack/plugin-auth...` (all exit 0).
- All 66 exit 0, including `check:i18n`, `check:dual-build-cjs-loads`,
`check:closing-keyword-parity`, `check:nul-bytes`,
`check:published-files` and `pnpm --dir ui exec vitest run scripts/`.
- `dispatch-gates --ran`: "66 derived famil(ies) accounted for — 66 run,
0 NOT-MEASURED", exit 0.
- `pnpm lint` (`eslint . --no-inline-config`): exit 0.
- Not run locally: `ui` type-check and the full `ui` test shards. CI's
Type Check UI and Test UI own them.
</details>
CI check-runs on this PR are the authority for every family CI runs.
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(not touched)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` passes.
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request. (the seat widened #27857's claim to carry #27869 (a))
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset.
- [x] 6. `packages/spec` touched: its generated artifacts are
regenerated and committed. (not touched)
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English.
- [x] The *Before Submitting* list in CONTRIBUTING.md is done.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_016WV4cwXFwjU2YZW2dRuZZt
---
_Generated by [Claude
Code](https://claude.ai/code/session_016WV4cwXFwjU2YZW2dRuZZt)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 85a1b9d commit b339465
18 files changed
Lines changed: 205 additions & 8 deletions
File tree
- .changeset
- packages/plugins/plugin-auth/src
- ui/packages
- app-shell/src/console
- __tests__
- auth/src
- __tests__
- i18n/src/locales
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
267 | 267 | | |
268 | 268 | | |
269 | 269 | | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
270 | 285 | | |
271 | 286 | | |
272 | 287 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
278 | 278 | | |
279 | 279 | | |
280 | 280 | | |
281 | | - | |
| 281 | + | |
282 | 282 | | |
283 | 283 | | |
284 | 284 | | |
| |||
694 | 694 | | |
695 | 695 | | |
696 | 696 | | |
697 | | - | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
698 | 702 | | |
699 | 703 | | |
700 | 704 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
407 | 407 | | |
408 | 408 | | |
409 | 409 | | |
410 | | - | |
| 410 | + | |
411 | 411 | | |
412 | 412 | | |
413 | 413 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
165 | 165 | | |
166 | 166 | | |
167 | 167 | | |
168 | | - | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
169 | 178 | | |
170 | 179 | | |
171 | 180 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
739 | 739 | | |
740 | 740 | | |
741 | 741 | | |
742 | | - | |
| 742 | + | |
743 | 743 | | |
744 | 744 | | |
745 | 745 | | |
| |||
749 | 749 | | |
750 | 750 | | |
751 | 751 | | |
752 | | - | |
753 | | - | |
754 | | - | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
755 | 755 | | |
756 | 756 | | |
757 | 757 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3064 | 3064 | | |
3065 | 3065 | | |
3066 | 3066 | | |
| 3067 | + | |
3067 | 3068 | | |
3068 | 3069 | | |
3069 | 3070 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2826 | 2826 | | |
2827 | 2827 | | |
2828 | 2828 | | |
| 2829 | + | |
2829 | 2830 | | |
2830 | 2831 | | |
2831 | 2832 | | |
| |||
0 commit comments