Skip to content

Post-login landing ignores isDefault — cold sign-in always lands on /_console/home (and AppManagementPage's Disable / Set-as-default are client-only stubs) #4233

Description

@huangyiirene

Symptom

A. Post-login landing ignores isDefault

With an app published carrying isDefault: true, four cold sign-ins in fresh browser contexts all landed on /_console/home instead of the default app.

  • Observed: /_console/home (the multi-app launcher), 4/4 cold sign-ins.
  • Expected: /apps/<the isDefault app>.
  • Control that isolates it: navigating to /_console/ while already authenticated redirects correctly to the default app. So the resolver's policy is fine; the unauthenticated entry path is what breaks.

B. AppManagementPage's Disable app and Set as default are client-only stubs (confirmed)

Both controls show a success toast with zero non-GET requests on the wire and no server change on reload. Nothing in section A was credited off those toasts — the isDefault: true app was published through metadata, not set via this UI.

Root cause

A — the chain

  1. On the unauthenticated first paint, GET /meta/app 401s.
  2. apps/console/src/components/RootLandingRedirect.tsx resolves with an empty app list. resolveLandingPath([]) has no isDefault entry and no single visible app, so it falls through to rule 3 and returns /home. The resolver is auth-unaware — it only distinguishes loading from resolved, not "resolved empty because 401".
  3. The auth guard then captures that already-wrong path into ?redirect=%2Fhome, and honors it after sign-in.
  4. So the isDefault branch never re-runs once the app list is actually available.

Verified still present on objectui origin/main @ bb68488: resolveLandingPath is unchanged (const defaultApp = list.find((a) => a.isDefault === true) on a list that is empty at that moment), and RootLandingRedirect still renders Navigate as soon as loading is false.

Not a stale bundle — the pin contains the routing (apps/console/src/components/RootLandingRedirect.test.ts asserts the isDefault policy at the pure-function level, which is exactly why the policy tests stay green while the live landing is wrong: the tests never feed it the empty-because-401 list).

B — the stubs

apps/console/src/pages/system/AppManagementPage.tsx — the handlers behind Set as default, Disable/bulk toggle and Delete each carry a literal // TODO: Replace with real API call when backend supports app management immediately before their toast.success(...), then call refresh(). No mutation is ever issued. Still present verbatim on origin/main @ bb68488 (the file's only recent touch is the i18n pass in #4208, which did not change the handlers).

Note the interaction between the two halves: because B never writes, an operator cannot even work around A from the console UI — isDefault has to be set in metadata.

Reproduction

Framework a86db175, vendored console 09987b68, showcase app.

A:

  1. Publish an app with isDefault: true.
  2. Open a fresh browser context (no session) and go to /_console/.
  3. Sign in.

Observed: lands on /_console/home; the sign-in URL carries ?redirect=%2Fhome. Repeated in 4 independent fresh contexts — 4/4.
Control: with an existing authenticated session, navigate to /_console/ — redirects correctly to the default app.

B:

  1. Go to the Applications page (AppManagementPage) as an admin.
  2. Click Disable app on an app, and Set as default on another.
  3. Watch the network panel; then reload.

Observed: success toast both times, zero non-GET requests, no server-side change after reload.

Dedup

Searched objectstack-ai/objectui for RootLandingRedirect, post-login landing / default-app landing, and AppManagementPage disable / set-as-default stub symptoms — no open or closed duplicate found.

Source

Extracted from the QA run objectstack-ai/objectstack#7514 (framework a86db175, vendored console 09987b6). Root-cause re-verification is against objectui origin/main @ bb68488.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions