Repository navigation
app-shell: DefaultRegisterPage renders an empty page for a signed-in visitor under invite_only — its bootstrap probe is gated on !user, so the offer stays pending forever #11714
Description
Activity
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsPath: ② the capabilities an end user meets in the app — sign-in and registration | 缺项 (no item asserts the published register page settles for a signed-in visitor) | P3
Triage: first grade —
bug·priority:p3·domain:ui·area:identity·pm:queue. A signed-in visitor is moved away, as the console's own page doesTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-06T11:53Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in
packages/app-shell/src/console/auth/RegisterPage.tsx(the probe gate, about:66, and thependingrender, about:76) and the README'suseSignUpOfferexample ⇒domain:ui; rationale: the page waits for an answer it never asks for when the visitor is signed in.Verified on
main(9ca3cacbeb):- The probe is gated on
!user. pendingrenders an emptyAuthPageLayout, and nothing re-renders it for a signed-in visitor.- The console's
/registermoves a signed-in visitor on in its post-sign-up effect.
Direction:
- A signed-in visitor on
DefaultRegisterPageis sent where the page sends a visitor after a successful sign-up. That is the console page's behaviour, and the page offers nothing a signed-in user can use. - It does not wait for the bootstrap probe.
- The README's
useSignUpOfferexample and its sign-up table say the same. - ⛔ The offer decision (
decideSignUpOffer) does not change. This is the page's handling of a visitor the decision is not about. - Honouring
?redirect=after sign-in stays out of scope, as the card says.
Pins:
- That visitor, over a real
AuthProviderwith a signed-in session, leaves/registerand never sees an empty layout. - objectui#11705's signed-out pins are unchanged.
Why p3: a signed-in user rarely opens
/register. When one does, the page is empty: nothing is offered wrongly and nothing breaks. The README example spreads the same gap to hosts that copy it.
Generated by Claude Code
- The probe is gated on
- addedarea:identityLogin and identity — sign-up, sessions, organization membership, SSOLogin and identity — sign-up, sessions, organization membership, SSObugSomething isn't workingSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seatand removed
on Oct 6, 2026 objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsClaim: PM loop round 1
Session:session_01FngvPpdrnhHMdHHq6vwwju
Account:os-justin
Branch:claude/issue-11714-register-signed-in-visitor
Worktree:objectui-issue-11714
Domain:domain:ui
Seat:domain:ui#2
File surface:packages/app-shell/src/console/auth/RegisterPage.tsx(DefaultRegisterPage: the probe gate about:66and thependingrender about:76);packages/app-shell/README.md(theuseSignUpOfferexample and the sign-up table objectui#11705 added); the tests beside them (__tests__/defaultPagesFollowPosture-11705.test.tsxstays green); and.changeset/11714-*.md(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: opus(dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate; default tier)
Clause-②: no
Thread-read: 6015672518
Ruling-ref: 6015672518 (triage: a signed-in visitor onDefaultRegisterPageis sent where the page sends a visitor after a successful sign-up, without waiting for the bootstrap probe; ⛔decideSignUpOfferdoes not change; honouring?redirect=after sign-in stays out of scope), retrieved this round.
Serial constraints cleared:noneblocking. No open PR touchespackages/app-shell/src/console/auth/**orpackages/app-shell/README.md. Read: objectui#11721, #11722, #11724, #11725, #11069 and the release PR objectui#11600. This seat's objectui#11720 dev is onconsole/organizations/manage/**, a different module of the same package; that is ordinary concurrency. Read 2026-10-06T15:36Z.Why
Clause-②: no: the fix changes what a published page does for a signed-in visitor: it moves them on instead of rendering an empty layout. It adds no export, prop, type member or locale key, and widens no accepted input. The README's example changes its text only.
Generated by Claude Code
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 11714, "status": "done", "branch": "claude/issue-11714-register-signed-in-visitor", "pr": "https://github.com/objectstack-ai/objectui/pull/11734", "session": "session_01FngvPpdrnhHMdHHq6vwwju — the dispatching seat's id (this is a subagent run; the container reads cse_01FngvPpdrnhHMdHHq6vwwju)", "premise_still_valid": true, "summary": "DefaultRegisterPage now latches when the first session check answers and, for a signed-in visitor, returns a react-router Navigate element to / with replace before any offer logic, so it never renders the form, the by-invitation notice or the pending empty layout for them. / is where the page already sends a visitor after a successful sign-up (RegisterForm onSuccess, unchanged). The bootstrap probe and the disableSignUp bounce to /login now run only for a visitor known to be signed out, so a signed-in visitor goes to /, never /login, and nobody is shown the form before the session answers. decideSignUpOffer, DefaultLoginPage and the objectui#11705 pins are byte-unchanged. The README table gains a signed-in row and its useSignUpOffer example answers signed-in for one, with a patch changeset. Draft PR objectui#11734 (head 2558521) is assigned to os-justin.", "tests": "Zone 2 #1 measured at base a58626c with a throwaway probe (real AuthProvider, signed-in /get-session): invite_only + owner + signed in stayed on /register with an empty AuthPageLayout and made no probe; open + signed in rendered the form; signed-out control showed the notice. Probe deleted before the first commit. || At 2558521: pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/console/auth/__tests__/ via os-verify-lock: VERDICT command-exit 0, Test Files 6 passed (6), Tests 34 passed (34). New file registerSignedInVisitor-11714.test.tsx has 4 cases; defaultPagesFollowPosture-11705.test.tsx (11 cases), signUpOffer-11691.test.ts and signUpOffer.ts have a 0-byte diff against base. || At 2558521: pnpm --filter @object-ui/app-shell type-check via os-verify-lock: VERDICT command-exit 0 (tsc --noEmit and tsc -p tsconfig.test.json; that project's --listFiles holds both changed source files, count 2, read at e23063f). Rebuilt dist/console/auth/RegisterPage.d.ts declares RegisterPage(): JSX.Element, as before; an earlier return-null draft emitted JSX.Element | null, which is why Navigate was used. || Ablation from committed 2558521: objectstack scripts/ablation-replace.mjs deleted the signed-in line (anchor 1 to 0, blob 683d5700 to b12a7137) with a trap restore, under the lock. Predicted 3 red and 12 green. Observed Tests 3 failed | 12 passed (15); all 3 fail with Unable to find an element by: [data-testid=\"home\"]. Restore: blob 683d5700335b equals the HEAD blob, git diff HEAD empty, git status --porcelain empty. The subject is imported by relative path from src, so there is no dist leg. || README leg: 'signed-in' changed to 'signed-inx' in the example gave check:doc-snippets exit 1 with TS2820 (not assignable to SignUpOffer | \"signed-in\") in the app-shell README block, 782 of 782 judged, 1 failed. Restored: blob c5c91ce18545 equals HEAD, git diff HEAD empty. || NOT MEASURED: whole app-shell suite (pnpm exec vitest run packages/app-shell/), reason: timeout 500 killed it (exit 124) with no verdict; left to CI pnpm test shards. Narrowing: every test naming DefaultRegisterPage or importing ../RegisterPage is in console/auth/__tests__ (git grep; the apps/console hits import the console's own page), and exports and the emitted declaration are unchanged.", "mcp_calls": "0 — no MCP GitHub tool was called", "api_writes": "3 — each one repository_dispatch POST /repos/objectstack-ai/objectstack/dispatches through the fleet relay: (1) pr_create, POST /repos/objectstack-ai/objectui/pulls (draft), read back 7392 of 7392 bytes identical; (2) label-write --assign os-justin, POST /repos/objectstack-ai/objectui/issues/11734/assignees, read back matches; (3) this os-dev-report comment, POST /repos/objectstack-ai/objectui/issues/11714/comments. Plus 5 git pushes (not REST): the empty branch, then commits cc1116c, ccbf358, e23063f, 2558521. Reads only: gh api GET issue 11714 with its comments, issue 11705 comments, PR 11734.", "gates": [ { "cmd": "pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/console/auth/__tests__/ (os-verify-lock)", "exit": 0, "head": "2558521" }, { "cmd": "pnpm --filter @object-ui/app-shell type-check (os-verify-lock)", "exit": 0, "head": "2558521" }, { "cmd": "pnpm lint (in packages/app-shell)", "exit": 0, "head": "2558521", "note": "0 errors; no finding in either changed file" }, { "cmd": "pnpm check:doc-snippets", "exit": 0, "head": "2558521", "note": "782 of 782 judged, 0 failed; closure from --build-filter built at e23063f, app-shell rebuilt at 2558521" }, { "cmd": "pnpm check:readme-exports", "exit": 0, "head": "2558521" }, { "cmd": "pnpm check:new-line-citations", "exit": 0, "head": "2558521" }, { "cmd": "pnpm check:control-bytes", "exit": 0, "head": "2558521" }, { "cmd": "pnpm check:changeset-claims", "exit": 0, "head": "2558521" }, { "cmd": "pnpm check:pending-changeset-literals", "exit": 0, "head": "2558521" }, { "cmd": "node scripts/check-changeset-no-major.mjs", "exit": 0, "head": "2558521" }, { "cmd": "node scripts/check-changeset-presence.mjs", "exit": 0, "head": "2558521" }, { "cmd": "node scripts/check-changeset-fixed.mjs", "exit": 0, "head": "2558521" }, { "cmd": "pnpm check:test-path-roots", "exit": 0, "head": "2558521" }, { "cmd": "node scripts/check-governed-queue-guard.mjs --test (4 changed paths)", "exit": 0, "head": "2558521", "note": "NOT GOVERNED" }, { "cmd": "pnpm exec vitest run --maxWorkers=2 packages/app-shell/ (os-verify-lock, timeout 500)", "exit": 124, "head": "e23063f", "note": "NOT MEASURED: killed by the timeout before a verdict; declared to CI" } ], "line_budget": "n/a — no skills/** in the diff. Line deltas against base a58626c: RegisterPage.tsx +30/-8, README.md +21/-9, registerSignedInVisitor-11714.test.tsx +221 (new), changeset +9 (new).", "files_changed": [ ".changeset/11714-register-signed-in-visitor.md", "packages/app-shell/README.md", "packages/app-shell/src/console/auth/RegisterPage.tsx", "packages/app-shell/src/console/auth/__tests__/registerSignedInVisitor-11714.test.tsx" ], "deviations": [ "Stray file /build.pid (6 bytes, holds PID 16902) at the filesystem root: a shell variable set inside a backgrounded && chain was empty in the foreground half of the command. The harness safety check refused rm /build.pid twice. Left for a person to delete; it is not in any repo.", "Zone 3 route changed with a measurement: render-null plus navigate() widened the emitted DefaultRegisterPage declaration to JSX.Element | null, so the signed-in branch returns a react-router Navigate element (renders nothing, navigates with replace from its own effect). The declaration stays JSX.Element.", "Zone 2 #2 reading: before the session check answers, the page still renders its existing empty AuthPageLayout placeholder, the same loading state every visitor gets; it cannot know who the visitor is yet. What is pinned is that no offer (form or notice) is ever mounted for a signed-in visitor, including when the config read lands before the session answer.", "The latch is a render-time setState rather than a layout effect, so the page adds no react-hooks/set-state-in-effect warning (the console page uses a layout effect).", "The measurement probe was a temporary test file inside the worktree, because vitest include globs need packages/**. It was deleted before the first commit and never committed.", "Attribution: the harness reminder asked for a model-named Co-Authored-By trailer and a different PR footer. Following AGENTS.md and os-dev.md, commits carry the model-free pair and the PR body ends with the session-URL footer.", "Order gate spelling pnpm --filter @object-ui/app-shell lint was run as pnpm lint inside packages/app-shell (same script). check-changeset-presence and check-changeset-fixed and check:test-path-roots were added beyond the named list.", "Cleanup done: /home/user/objectui-issue-11714 node_modules removed and git worktree remove succeeded (tree clean, remote branch at 2558521). No dev server or background job of mine is still running." ], "open_questions": [], "out_of_scope_findings": [ "carrier: none · noted in PR Acceptance notes, not filed — DefaultLoginPage does not single out a signed-in visitor: it renders the sign-in form. Read from source; the card covers the register page only.", "carrier: none · noted, not filed — after a successful sign-up, RegisterForm onSuccess pushes / and the signed-in branch replaces with /; which runs first decides whether history holds one or two entries. Measured once in the test DOM, only the REPLACE showed; the visitor lands on / either way.", "carrier: none · noted, not filed — the Navigate element renders nothing while it navigates. chrome/RedirectWithSplash.tsx documents that blank window on the console boot path; here it follows the page's own empty placeholder. Read, not measured." ] }
Generated by Claude Code
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsACCEPT: PR objectui#11734 at
2558521(Fixes #11714). No contract review is owed; it lands when CI is greendomain:uiexecution seat 2 ·session_01FngvPpdrnhHMdHHq6vwwju(os-justin) · 2026-10-06T16:49Z. Dev report:os-dev-report6021063150on this card. Claim6019801360.-
Shape:
- The PR is a draft on base
main(merge-basea58626c). Its first line isFixes #11714, andClause-②: nostarts a line. - It has 4 files, +281/−17, all inside the claim's surface.
git merge-treeagainstmainat0cfe772is clean. NOT GOVERNED. The assignee isos-justin. - The commits:
cc1116c(the fix),ccbf358(the README), thene23063fand2558521, two refactors that settle the shape below.
- The PR is a draft on base
-
Measured before the fix (dev, at
a58626c, realAuthProvider, signed-in/get-session):- under
invite_onlywith an owner, a signed-in visitor stayed on/registerwith an emptyAuthPageLayout, and no probe ran; - under
open, a signed-in visitor got the form; - the signed-out control showed the by-invitation notice.
That is the card's premise.
- under
-
Seat's own reading of the diff (
RegisterPage.tsx, +30/−8):- The page latches the first session answer while rendering (
sessionChecked), because everysignUpin flight raisesisLoadingagain, and a sign-up in flight must not unmount the form and the refusal it holds. The console's own register page latches it the same way. signedOut = sessionChecked && !usergates both the bootstrap probe and thedisableSignUpbounce. So a signed-in visitor never goes to/login, and no one is offered the form before the session answers.- With a user, the page returns
<Navigate to="/" replace />after every hook, so the hook order is unchanged./is whereRegisterForm'sonSuccessalready sends a visitor. - The verification screen (
pendingEmail) is set only byonVerificationRequired, which runs for a sign-up that left no session, so the redirect does not cut it off. decideSignUpOffer,DefaultLoginPageand the objectui#11705 pins have a 0-byte diff.
- The page latches the first session answer while rendering (
-
Clause-②: no, confirmed:
- No export, prop, type member or i18n key is added.
<Navigate>was chosen overreturn nullby measurement:return nullwidened the emittedDefaultRegisterPagedeclaration toJSX.Element | null. The rebuiltdist/console/auth/RegisterPage.d.tskeepsJSX.Element.- The README's
useSignUpOfferexample is user code in the docs, not a package export. ItsSignUpOffer | 'signed-in'return type adds nothing to the entry.
-
Changeset (
@object-ui/app-shell:patch), checked sentence by sentence against the diff:- the signed-in redirect and its target;
- the wait for the session check before anything is offered or probed;
decideSignUpOfferandDefaultLoginPageunchanged;?redirect=out of scope;- the README row and example.
patchfits a behaviour fix with no surface change. -
Tests and gates (dev, measured at
2558521):console/auth/__tests__/: 6 files, 34 tests, green, including the newregisterSignedInVisitor-11714.test.tsxwith 4 cases.type-check(both programs) andlint: 0 errors.check:doc-snippetsjudged 782 of 782 with 0 failed, and its README leg was proven by a typo ablation that went red.check:readme-exports, the changeset gates,check:new-line-citationsandcheck:control-bytes: all exit 0.- One ablation leg (the signed-in line removed) went 3 red / 12 green as predicted, and was restored by blob.
- Declared as NOT MEASURED: the whole
app-shellsuite, which timed out locally with no verdict; CI's shards own it. The narrowing holds, because every test namingDefaultRegisterPagesits inconsole/auth/__tests__.
-
Out-of-scope findings (3), Acceptance note, not filed:
DefaultLoginPagerenders the sign-in form for a signed-in visitor. The card covers the register page only.- After a sign-up, the
onSuccesspush and the redirect's replace race over one history entry; the visitor lands on/either way. <Navigate>renders nothing while it navigates.
-
Raised to the maintainer, not redone by the seat: a stray
/build.pid(6 bytes) at this container's filesystem root, left by a dev shell line. The dev's session refused itsrmtwice. It is in no repository, and the seat does not redo a refused action. -
CI on
2558521: in progress at this read (26 success, 3 skipped, 13 running, 0 failed).
Generated by Claude Code
-
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsLanded: PR objectui#11734 →
main2b635e5, verified by content.Fixesclosed this carddomain:uiexecution seat 2 ·session_01FngvPpdrnhHMdHHq6vwwju(os-justin) · 2026-10-06T17:20Z.-
The merge.
- Squash
2b635e5went through the merge queue. It has one parent,6be0f7a, and is an ancestor oforigin/main. - 4 files, +281/−17.
- The landed tree equals
git merge-treeof the parent and the reviewed head2558521(tree2c3022d6…on both). - The changed lines are identical (md5
2faeefe9…on both).mainhad moved past the PR's merge-basea58626c, so only the hunk offsets differ.
- Squash
-
No contract review was owed:
Clause-②: no(ACCEPT6021098691). -
Content check against the first parent:
reading 6be0f7a2b635e5<Navigate to="/" replace />inconsole/auth/RegisterPage.tsx0 1 __tests__/registerSignedInVisitor-11714.test.tsxpresent0 1 the README sign-up table's signed inrow0 1 -
Closures.
Fixes #11714closed this card as completed at the merge. No other issue closed in the landing window.pm:dispatchedcomes off in this stroke. -
Recorded, not filed:
DefaultLoginPagerenders the sign-in form for a signed-in visitor.- The post-sign-up push and the redirect's replace race over one history entry, and the visitor lands on
/either way. <Navigate>renders nothing while it navigates.
Generated by Claude Code
-
- added a commit that references this issue
on Oct 7, 2026
Filing gate ①: a product defect with a named location and a named producer.
Reader: the objectstack-wide triage seat's first touch (grade and route), then the
domain:uiexecution seat that claims it.Dedupe:
mcp__github__search_issueson objectstack-ai/objectui, closed included, for "DefaultRegisterPage signed-in visitor register page empty blank invite_only pending already signed in", gives 6 hits. None of them is this defect:Positive control: #11705 and #11030 are cards on this same exported page.
What happens
DefaultRegisterPage(packages/app-shell/src/console/auth/RegisterPage.tsx, onmainat7e2d5b0) asksdecideSignUpOfferwhat to offer. Under an audience posture closed to strangers (invite_only, the server's default), with no invitation redirect, the decision needs the bootstrap probe, and answerspendinguntil the probe does.useBootstrapStatus(!user && needsBootstrapProbe(authConfig, invitationRedirect))(about:66).'unknown'and the offer stayspending.AuthPageLayoutforpending(about:76), and nothing ever changes it.So a signed-in user who opens
/registerunderinvite_onlygets an empty layout with no text, no form and no link. Before objectui#11705 that visitor got the form, which the server would refuse.examples/console-starter/src/App.tsxmountsDefaultRegisterPageat/register(about:52) with no signed-in redirect or guard.packages/app-shell/README.md, about:214) says the/registerpage shows "registration is by invitation" before any form for "invite_only, anyone else".6014912328) and by the seat. No render probe was run. The console's own/register(apps/console/src/pages/auth/RegisterPage.tsx) moves a signed-in visitor away, so it does not show this.useSignUpOfferexample gates the probe on!userthe same way, so a host that copies it inherits the samependingfor a signed-in visitor.Done when
DefaultRegisterPageunderinvite_only, with no invitation redirect, sees a settled page: the by-invitation notice, or a redirect away. Never an empty layout.AuthProviderwith a signed-in session, does not get an emptyAuthPageLayout. The signed-out pins of objectui#11705 are unchanged.Not this card: after a successful sign-in or sign-up, the default pages navigate to
/and do not honour?redirect=. objectui#11711 notes that in its Acceptance notes, and it is not filed, because no in-repo producer mountsDefaultAcceptInvitationPagebeside these pages.Related: objectui#11705 (PR objectui#11711) · objectui#11691.
Dedupe words:
DefaultRegisterPage signed-in pending·useBootstrapStatus !user register·register page empty invite_only·console-starter register signed inFiled by the
domain:uiexecution seat 2 (session_01FngvPpdrnhHMdHHq6vwwju) from objectui#11711's contract review. ⛔ Not graded or routed here; ⛔ not a claim.Generated by Claude Code