Repository navigation
Invitation landing never reads the signed-out invitation preview (#26020 landed server-only): login/register still cannot name the organization or inviter #26473
Description
Filing gate ① a follow-up owed by landed work (class a, public door: the invitation link). reach: one browser, local stack, cloud PR #3297 head 4e7ee6d5 + framework pin 6390fe52, zh-CN, 2026-10-27. Signed out, opening an invitation link shows 「接受邀请 · 请使用收到邀请的邮箱。 · 注册并加入」, and 注册并加入 shows 「注册账号并加入」. Neither page names the inviting organization or the inviter, and the email is not prefilled. The server read built for exactly this works anonymously on the same stack: GET /api/v1/auth/organization/invitation-preview?id=EKPx8… → {"organizationName":"晓林装饰工作室","inviterName":"林晓","email":"z***@example.com"} (unknown id → 404).
Batch-of: 5 · 2026-10-27 re-test of the 2026-10-25 desktop E2E after the fixes. Filed at the maintainer's request: 「完整的再测试一遍」 / 「必要的合理的建议都可以立卡」. Reviewed in-session before filing.
Business reason. Every seat after the first arrives through this page. The point of #25886 and #26020 was that an invitee sees "林晓 invited you to 晓林装饰工作室" before being asked for anything. That read exists now, but nothing displays it. The ui read fell between two closes: #26020's body says "After it lands, the ui seat reads the new route in LoginPage.tsx / AcceptInvitationPage.tsx under #25886, which stays open for that". But #25886 closed COMPLETED (2026-10-26T16:55Z, "the server half was split to #26020"), and #26020 closed on PR #26151, which touched no ui/ file.
Reader who acts. The domain:ui seat: ui/packages/auth (client method) and ui/packages/app-shell/src/console/auth + organizations/manage.
Where (pin 6390fe52; no ui consumer on objectstack main either)
- No reader:
git grep -l "invitation-preview|invitationPreview" -- ui/finds nothing. The ui auth client has only the session-gatedgetInvitation(ui/packages/auth/src/createAuthClient.ts:1005). - The server route:
packages/plugins/plugin-auth/src/invitation-preview.ts, ledgered inauth-route-ledger.ts:261(closed query set{ id }, masked email, uniform 404, per-address rate limit). - Pages that should read it:
app-shell/src/console/auth/LoginPage.tsx:121-134, 196-208(generic invitation title/description)RegisterPage.tsx:230-233invitationArrival.tsx:48ui/apps/console/src/pages/auth/LoginPage.tsx:330-341organizations/manage/AcceptInvitationPage.tsx:25-32, 211-240(names org/inviter only when signed in, via get-invitation)
Expected
- On an
/accept-invitation/<id>redirect, login, register and accept read the preview and say 「林晓 邀请你加入 晓林装饰工作室」. - Register shows the masked address as the expected one and warns when the typed address doesn't match its pattern. Full prefill isn't possible from a masked value.
- An unknown or expired id falls back to today's generic copy.
- Optional: the environment-host login's 「欢迎回来」 on a member's first visit could greet "from ObjectOS Cloud" now that PR cloud#3286 carries an entry identity. Taste; take it only if trivial.
Dedupe
gh api search/issues, incl. closed:
- objectstack
invitation-preview login prefill: 3 (Invitation link while signed out: the generic 欢迎回来 login page with no inviter or organization, no prefilled email, and a second verification mail after sign-up #25886 closed, plugin-auth: a signed-out invitation preview read, so the invitation landing page can name the inviting organization and the inviter (server half of #25886) #26020 closed, [PM seat] triage (objectstack-wide) — 🟢 Routine · session_01AavokzJ5DndAwitDXvKy4U · trig_01NcnCtMS2tH46nUg1a5TaMJ (hourly) · state = body + the round records newer than it #6015 seat). - objectstack
invitation preview ui organization inviter signed-out: 3, the same. - cloud
invitation preview login organization: 3 (feat(cli): surface migration guide when specVersion trails the installed platform #2914, build-skill-references.ts: import regex is blind to multi-line imports, under-reporting skill schema deps #3139, [downstream/hotcrm] Migrate approval approvers from { type: 'role' } to { type: 'position' } (ADR-0090 D3) #2777), unrelated.
Activity
objectstack-fleet commentedon Oct 27, 2026
Triage: audit line · triage seat ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-27T05:14Z⛔ Not a claim, ⛔ not a dispatch. The filer's labels are read and kept; this is the triage line an execution seat needs before it claims.
domain:ui·area:identity. The ui half of plugin-auth: a signed-out invitation preview read, so the invitation landing page can name the inviting organization and the inviter (server half of #25886) #26020: the signed-out preview read (GET /api/v1/auth/organization/invitation-preview) is onmainand answers anonymously. The page should read it and show the organization, the inviter and the masked email, within plugin-auth: a signed-out invitation preview read, so the invitation landing page can name the inviting organization and the inviter (server half of #25886) #26020 ruling A's boundary. ⛔ No field beyond what the read returns.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim: PM loop round 12 · 2026-10-27T05:26Z
Session:
session_01SMps7wq7rBTk53e8KTSEupAccount:
os-steveBranch:
claude/issue-26473-invitation-preview-landingWorktree:
objectstack-issue-26473Domain:
domain:uiSeat:
domain:ui#2File surface:
ui/packages/app-shell/src/console/auth/invitationArrival.tsx,ui/packages/app-shell/src/console/organizations/manage/AcceptInvitationPage.tsx, the console sign-up page it hands to,ui/packages/auth/src/createAuthClient.ts(a read method if one is missing), tests beside them, root.changeset/. ⛔signUpOffer.ts(open PR #26483). ⛔ locale packs underui/packages/i18nunless the card needs a new key (then en + zh only, and say so),ui/.github/**, rootci.yml.Container & model:
M,mode:subagent,model: default tier,effort: mediumClause-②: no
Metadata-protocol: none
Responsibility:
an invitee who opens an invitation link signed out|GET /api/v1/auth/organization/invitation-preview(#26020) |every invited seat after the firstThread-read: none
Premise: holds 2026-10-27T05:26Z at
origin/main00a4593ad7:invitationArrival.tsx/AcceptInvitationPage.tsxnever call the invitation-preview read; the card measured the page naming neither the organization nor the inviter.Serial constraints cleared: #26020 (server read) closed; no open PR touches these files except
signUpOffer.ts(#26483), which is off this surface.Writes: PR only via the relay op
pr_create; comments only via the relay write tools; ⛔ no GitHub MCP writes.Fixes #26473.objectstack-fleet commentedon Oct 27, 2026
os-dev-report
{ "issue": 26473, "status": "done", "branch": "claude/issue-26473-invitation-preview-landing", "pr": "https://github.com/objectstack-ai/objectstack/pull/26554", "head": "b848d2b1", "session": "session_01SMps7wq7rBTk53e8KTSEup (subagent; the parent's id)", "premise_still_valid": true, "summary": "The auth client, AuthProvider and useAuth() gain getInvitationPreview(id), which sends one anonymous GET to /organization/invitation-preview. It returns the preview, null on 404, or rejects with code and status on any other failure. app-shell gains useInvitationPreview(redirect) and invitationArrivalCopy(page, preview, t). DefaultLoginPage, DefaultRegisterPage and the console's own /login and /register now title an invitation arrival 'INVITER invited you to join ORG' and show the masked address as the address to use. The email field is never prefilled. On a 404, a failed read or an older server, each page keeps today's generic copy and nothing throws. Four new keys are in all ten locale packs, not en+zh only (see deviations).", "tests": "Red first, under the lock: the 14 implementation files were restored to base 00a4593a in the working tree only and the new files run. auth file 5/5 failed (client.getInvitationPreview is not a function). app-shell file 9/10 failed; the passing one is the no-invitation preservation pin, as expected. console file 6/6 failed. Restore proven by hash comparison and an empty git diff HEAD. Green at b848d2b1: vitest over packages/auth/ + packages/i18n/ + the 13 app-shell test files that import the touched pages gave Test Files 136 passed (136), Tests 1781 passed | 13 skipped. Console project over the 21 console test files that import the console Login/Register pages gave Test Files 21 passed (21), Tests 110 passed (110). type-check exit 0 for @object-ui/auth, @object-ui/i18n, @object-ui/app-shell and @object-ui/console. Closure build pnpm --filter '@object-ui/console^...' build gave VERDICT command-exit 0. No ablation beyond the red leg.", "gates": "Derived (--commands, 34) at b848d2b1: 32 exit 0. pnpm --dir ui exec vitest run scripts/ exit 99, lock queue-timeout three times: NOT MEASURED. pnpm check:type-check-debt exit 3, PREREQUISITE NOT MET because its re-measure build never got a lock turn: NOT MEASURED. --ran: 34 accounted, 33 run, 1 NOT-MEASURED; the tool classifies exit 3 only, so the exit-99 run is NOT MEASURED too. Extra: node scripts/check-sdui-manifest.mjs exit 0 (no registry contract change, nothing regenerated), ui check:i18n-keys / check:i18n-drift / check:i18n-dead-keys exit 0, pnpm check:changeset-fixed exit 0 (the roster flagged for .changeset), check:nul-bytes exit 0. CI check-runs not yet concluded: in_progress at report time.", "dogfood_battery": "n/a: no '!' in the PR title and no (narrowing) arm", "line_budget": "26 files, +809 / -46 (855 changed lines; under the 3000 human-merge threshold)", "files_changed": [ ".changeset/26473-invitation-preview-landing.md", "ui/packages/auth/src/{types,AuthContext,useAuth,index,createAuthClient}.ts, AuthProvider.tsx, __tests__/invitationPreview-26473.test.ts", "ui/packages/app-shell/src/console/auth/{invitationArrival,LoginPage,RegisterPage}.tsx, __tests__/invitationPreview-26473.test.tsx, src/index.ts", "ui/apps/console/src/pages/auth/{LoginPage,RegisterPage}.tsx, __tests__/invitationPreview-26473.test.tsx", "ui/packages/i18n/src/locales/{en,zh,ar,de,es,fr,ja,ko,pt,ru}.ts (4 added keys each; en comment updated)" ], "deviations": [ "Locale packs: the dispatch said en and zh only. Measured under the lock, en+zh only reds ui/packages/i18n/src/__tests__/all-locales-key-parity.test.ts: Tests 8 failed | 40 passed, one per other locale ('ar is missing 4 key(s)'). The four keys are therefore in all ten packs, on new lines only, no existing value changed. The PR body says so. #26469 also edits these packs, so a conflict would be about line placement only.", "File surface: beyond the claim's named files, the diff touches both LoginPage.tsx and both RegisterPage.tsx (the card lists them), auth types.ts / AuthContext.ts / AuthProvider.tsx / useAuth.ts / index.ts (to reach the read from a page), and app-shell index.ts (export). AcceptInvitationPage.tsx is untouched: a signed-out visitor is redirected away from it before it renders. signUpOffer.ts is untouched (#26483).", "Two derived gates NOT MEASURED locally because of lock starvation; CI runs both. Holder at the last attempt: pid 11361, scratchpad/issue-26415/lock1.sh, held 1296s.", "The harness's own Co-Authored-By trailer instruction names a model; per AGENTS.md, commits carry the model-free pair (Claude-Session + Co-authored-by: Claude). Reported, not a deviation of record." ], "mcp_calls": "0. No MCP GitHub tool was called.", "api_writes": "2 relay strokes. (1) pr_create: POST /repos/objectstack-ai/objectstack/dispatches; the relay ran POST /repos/objectstack-ai/objectstack/pulls (draft #26554) + POST /repos/objectstack-ai/objectstack/issues/26554/assignees [os-steve], run 40471076863 success, body read back identical (9361 bytes). (2) This os-dev-report comment through post-stamped.mjs: POST /repos/objectstack-ai/objectstack/issues/26473/comments. git push is not counted.", "open_questions": [ { "question": "The card also suggested a register-page warning when the typed address does not match the masked pattern. The seat's route did not include it, so it is not done. Add it in a follow-up?", "options": [ "A: no; the server refuses a non-invitee's sign-up already and the masked address is shown", "B: a small follow-up that compares first letter + domain on blur" ], "recommendation": "A, because the server is the authority and a client-side pattern guess adds a second, weaker check" } ], "out_of_scope_findings": [ "carrier: none (承接者:无) · invitationIdOf in invitationArrival.tsx and isInvitationRedirect in signUpOffer.ts read the same /accept-invitation/ segment; once #26483 lands, isInvitationRedirect can be invitationIdOf(r) !== null. Noted in Acceptance notes, not filed." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Landed · seat 2 · 2026-10-27T09:02Z
319d6fa0, headb848d2b1(+809/−46, seat record on #26554)origin/maingit merge-base --is-ancestorexit 0)gh-readonly-queue/main/pr-26554-*: none left (consumed)Fixes #26473on #26554Status: a signed-out visitor opening an invitation link sees who invited them and to which organization on the sign-in and sign-up pages (the server's masked invitee address as a hint, never prefilled); a missing or failed preview keeps the generic copy.
pm:dispatchedremoved.