Repository navigation
feat(ui): the signed-out invitation landing names the inviter and the organization from the invitation preview - #26554
Conversation
…gin and register pages (wip) Claude-Session: https://claude.ai/code/session_01SMps7wq7rBTk53e8KTSEup Co-authored-by: Claude <noreply@anthropic.com>
… found / 404 / failure (wip) Claude-Session: https://claude.ai/code/session_01SMps7wq7rBTk53e8KTSEup Co-authored-by: Claude <noreply@anthropic.com>
…key parity requires Claude-Session: https://claude.ai/code/session_01SMps7wq7rBTk53e8KTSEup Co-authored-by: Claude <noreply@anthropic.com>
… pages Claude-Session: https://claude.ai/code/session_01SMps7wq7rBTk53e8KTSEup Co-authored-by: Claude <noreply@anthropic.com>
维护者速读改了什么:未登录时打开邀请链接,登录页和注册页会读取服务端的匿名邀请预览( 席位核对seat 2 · 2026-10-27T08:23Z · head
|
Fixes #26473
Clause-②: no
Metadata-protocol: none
维护者速读
GET /api/v1/auth/organization/invitation-preview),卡片标题变为「林晓 邀请你加入 晓林装饰工作室」,并显示打码后的受邀邮箱作为提示。ui/packages/app-shell/src/console/auth/invitationArrival.tsx的useInvitationPreview与invitationArrivalCopy;ui/packages/auth/src/createAuthClient.ts的getInvitationPreview。pnpm --dir ui exec vitest run packages/app-shell/src/console/auth/__tests__/invitationPreview-26473.test.tsx packages/auth/src/__tests__/invitationPreview-26473.test.ts,预期全绿。What changes
@object-ui/auth.getInvitationPreview(invitationId)is added toAuthClient,AuthContextValue,AuthProvideranduseAuth(), along with the exportedAuthInvitationPreviewtype (organizationName,inviterName: string | null,email). The client sends one anonymousGET {authUrl}/organization/invitation-preview?id=IDwith the id URL-encoded. It handles the answers this way:{ success: true, data }: the three keys, checked at the boundary.null. The server sends one uniform not-found for an unknown, expired, accepted, rejected or cancelled id, so this is an answer, not a failure.codeand the HTTPstatus.getInvitationPreview. The page never gets a half-filled sentence.@object-ui/app-shell.invitationArrival.tsxgainsuseInvitationPreview(redirect)andinvitationArrivalCopy(page, preview, t), and both are exported from the package entry.?redirect=/accept-invitation/ID, using the same segmentisInvitationRedirecttests. It returns the preview for the current id only. It returnsnullwhile the read is pending, for a 404, and after any failure, including auseAuth()double that lacks the method. None of these throws into the page.DefaultLoginPageandDefaultRegisterPageuse both for an invitation redirect.@object-ui/console. The console's own/loginand/register(apps/console/src/pages/auth/) do the same. They are the pages the console routes.The masked email. The preview's
emailis masked by the server (z***@example.com). It appears only in the card's description. No field is filled from it, and the pins assert that the email input stays empty.@object-ui/i18n. Four keys are added:auth.login.invitationPreviewTitle,auth.login.invitationPreviewTitleNoInviter,auth.login.invitationPreviewDescriptionandauth.register.invitationPreviewDescription.Locale packs: all ten, not en and zh only
The dispatch asked for new strings in en and zh only. That was measured, and it reds
ui/packages/i18n/src/__tests__/all-locales-key-parity.test.ts. That test requires every pack to define every en key, and its only exception is the four outbound AI-message keys. The run under the lock with en and zh only:Tests 8 failed | 40 passed (48), one failure per other locale, for examplear is missing 4 key(s): auth.login.invitationPreviewDescription, auth.login.invitationPreviewTitle, auth.login.invitationPreviewTitleNoInviter, auth.register.invitationPreviewDescription. So the four keys are added to ar, de, es, fr, ja, ko, pt and ru as well, each on its own new lines next to the existing invitation keys.Tests (red first)
New files:
ui/packages/auth/src/__tests__/invitationPreview-26473.test.ts(5 tests). Cases: found (exact keys, one GET, encoded id); found with a null inviter; 404 resolvesnull; 429 rejects withcodeandstatus; a wrong-shape 200 rejects.ui/packages/app-shell/src/console/auth/__tests__/invitationPreview-26473.test.tsxcoversDefaultLoginPageandDefaultRegisterPage, rendered through a realAuthProvider, a realcreateAuthClientand a realI18nProvider, with onlyfetchstubbed. Cases:ui/apps/console/src/pages/auth/__tests__/invitationPreview-26473.test.tsxruns found, 404 and 500 on the console's/loginand/register.The red leg was run under the lock: the 14 implementation files were restored to the base
00a4593ain the working tree only, the new files were run, and then the files were restored toHEAD. The restore was proved by hash comparison and an emptygit diff HEAD.Red, with the implementation at base:
client.getInvitationPreview is not a function).Green at head: see Verification.
Acceptance notes
invitationIdOfininvitationArrival.tsxreads the same/accept-invitation/segment asisInvitationRedirectinsignUpOffer.ts. That file is in open PR chore(ui)!: stop publishing @object-ui/app-shell; delete the two host-console examples and the extraction guide (#25922) #26483 and was not touched here. Once chore(ui)!: stop publishing @object-ui/app-shell; delete the two host-console examples and the extraction guide (#25922) #26483 lands,isInvitationRedirectcould be expressed asinvitationIdOf(r) !== null, leaving one parser.AcceptInvitationPageis unchanged. A signed-out visitor is redirected from it to/loginbefore it renders, and a signed-in visitor already gets the organization throughget-invitation.invitationArrival.tsx,AcceptInvitationPage.tsx, the console sign-up page,createAuthClient.tsand the locale packs. This diff also touches four files the card itself lists (bothLoginPage.tsxfiles and bothRegisterPage.tsxfiles), the auth package'stypes.ts,AuthContext.ts,AuthProvider.tsx,useAuth.tsandindex.ts(needed to reach the read from a page), the app-shellindex.tsexport, and all ten locale packs.Verification
All runs are on head
b848d2b1, in a worktree based onorigin/main00a4593a. Heavy runs went throughscripts/pm/os-verify-lock.sh.Closure:
pnpm --workspace-concurrency=2 --filter '@object-ui/console^...' buildgaveVERDICT command-exit 0.vitest run(fromui/) overpackages/auth/,packages/i18n/and the 13 app-shell test files that import the touched pages (the new file included):Test Files 136 passed (136),Tests 1781 passed | 13 skipped (1794).Console project, over the 21 console test files that import the two console pages (the new file included):
Test Files 21 passed (21),Tests 110 passed (110).pnpm --filter X run type-checkexited 0 for each of@object-ui/auth,@object-ui/i18n,@object-ui/app-shelland@object-ui/console.ui i18n gates
check:i18n-keys(it checks every inlinedefaultValueagainst the en pack),check:i18n-driftandcheck:i18n-dead-keys: exit 0.node scripts/check-sdui-manifest.mjs: exit 0. No registry component contract changed, so the manifest is not regenerated.Derived gates (
dispatch-gates.mjs --commands): 34 commands. 32 exited 0. Two were not measured, and CI runs both:pnpm --dir ui exec vitest run scripts/exited 99, a lock queue-timeout, three times.pnpm check:type-check-debtexited 3, PREREQUISITE NOT MET, because its re-measure build never got a lock turn. The four touched packages' own type-checks are green above.The
--ranreconciliation reads 34 accounted, 33 run, 1 NOT-MEASURED. The tool classifies exit 3 only, so the exit-99 vitest run counts as NOT MEASURED here as well.pnpm check:changeset-fixedandpnpm check:nul-bytes: exit 0.Generated by Claude Code