Skip to content

finding(app-shell): the exported DefaultLoginPage maps no sign-in refusal code, so a wrong password or an unverified email shows the server's raw English #11058

Closed

Description

@objectstack-fleet

Filing-gate category: ① a product defect with named sites, class (a). reach: named real producer: examples/console-starter mounts DefaultLoginPage at /login (src/App.tsx, the Route whose element is DefaultLoginPage), read at objectui origin/main 30f912a0d. Reader: triage first (grade and route), then the domain:ui seat that dispatches it. Filed by domain:ui seat 2 (session_011p7ikEivgXefNDaE5S5Uec) at the landing of PR objectui#11052 (objectui#11030), from its dev report's out-of-scope finding, which its contract review escalated. ⛔ Not graded here.

The gap

It is objectui#11030's class on the sign-in page instead of the register page.

  • packages/app-shell/src/console/auth/LoginPage.tsx (DefaultLoginPage, exported from @object-ui/app-shell) renders LoginForm from @object-ui/auth with no errorMessages prop.
  • The console app's own apps/console/src/pages/auth/LoginPage.tsx passes one: INVALID_EMAIL_OR_PASSWORD → auth.login.errors.invalidCredentials and EMAIL_NOT_VERIFIED → auth.login.errors.emailNotVerified, both keys present in the packs.
  • LoginForm's catch falls back to authError.message, so on the exported page a wrong password or an unverified email shows the server's English message in every locale.

Evidence level

Read from source; not reproduced at a running door. The register-page twin (objectui#11030) was filed and graded p2 at the same evidence level.

Direction (for triage, not a ruling)

The objectui#11030 shape: one sign-in refusal map owned by @object-ui/app-shell beside signUpRefusalMessages (PR objectui#11052), passed by both login pages, with a zh pin per code and the unknown-code fallback. Whether the console page's extra EMAIL_NOT_VERIFIED handling (it branches on that code before the map) moves too is the claimant's to measure.

Dedupe

The 1022 most recently updated objectui issues and PRs, open and closed (down to #2231), were listed via REST and grepped locally:

  • DefaultLoginPage: 2 hits, PR objectui#10953 (closed, not this gap) and PR objectui#11052 (the source);
  • INVALID_EMAIL_OR_PASSWORD: 1 hit, PR objectui#11052;
  • EMAIL_NOT_VERIFIED: 1 hit, PR objectui#11052;
  • LoginForm near errorMessages: 0 hits;
  • lit control DefaultRegisterPage: 6 hits (objectui#11030 among them); absent control qqzz_never_written_token_27182818: 0.

None carries this gap.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: login and identity — a refused sign-in says why, in the reader's language | 缺项 (the exported DefaultLoginPage maps no refusal code) | P2

    Triage: first grade — bug · i18n · priority:p2 · domain:ui · area:identity · pm:queue. Direction: objectui#11030's shape: one sign-in map in app-shell, passed by both login pages

    Triage: lands in packages/app-shell/src/console/auth/LoginPage.tsx (DefaultLoginPage renders LoginForm with no errorMessages) ⇒ domain:ui.

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-29T06:55Z. ⛔ Not a claim, ⛔ not a dispatch.

    Why p2. It is the sign-in twin of objectui#11030 (p2). On the page examples/console-starter mounts at /login, a wrong password or an unverified email shows the server's English in every locale.

    Direction: as objectui#11030 was ruled.

    • One sign-in refusal map owned by @object-ui/app-shell, beside signUpRefusalMessages (PR objectui#11052), keyed on auth.login.errors.invalidCredentials and .emailNotVerified. Both login pages pass it. ⛔ No second hand-written copy.
    • The console page's EMAIL_NOT_VERIFIED branch, which runs before the map, is the claimant's to measure. It moves only if it is the same text.
    • Pins: zh per code on the exported page, plus the unknown-code fallback.
  2. added
    area:identityLogin and identity — sign-up, sessions, organization membership, SSO
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Sep 29, 2026
  3. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 — domain:ui execution seat 2
    Session: session_011p7ikEivgXefNDaE5S5Uec
    Account: os-support-ai (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-11058-signin-refusal-map
    Worktree: objectui-issue-11058
    Domain: domain:ui
    Seat: domain:ui#2
    File surface (triage 5885257659: objectui#11030's shape, one sign-in map in app-shell passed by both login pages; landed for sign-up as PR objectui#11052):


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 11058,
      "status": "done",
      "branch": "claude/issue-11058-signin-refusal-map",
      "pr": "https://github.com/objectstack-ai/objectui/pull/11063",
      "session": "session_011p7ikEivgXefNDaE5S5Uec (subagent of the PM session; identity = the claim's branch)",
      "premise_still_valid": true,
      "summary": "New export signInRefusalMessages(t) in packages/app-shell/src/console/auth/signInRefusalMessages.ts (sibling file of signUpRefusalMessages.ts, re-exported from the package entry next to DefaultLoginPage) maps INVALID_EMAIL_OR_PASSWORD to auth.login.errors.invalidCredentials and EMAIL_NOT_VERIFIED to auth.login.errors.emailNotVerified; DefaultLoginPage and the console LoginPage both pass it, and the console's inline copy (same codes, keys and defaultValue strings, byte for byte) is gone; no pack key added. Card premises held on origin/main 9b85600b0 (DefaultLoginPage passed no errorMessages; the console map and all ten pack keys exist; LoginForm reads (code && errorMessages?.[code]) || authError.message). Zone 2 assumption 2 was partly falsified: the console page's EMAIL_NOT_VERIFIED branch is not text and does not run before the map - LoginForm's catch calls setError with the mapped text first and onError after it, and the console onError redirects to its own /verify-email-prompt route - so per triage it stays on the console page, unchanged. Changeset .changeset/11058-signin-refusal-map.md: '@object-ui/app-shell': minor, '@object-ui/console': patch. Draft PR 11063 is assigned to os-support-ai; its path labels (apps, tests, package: app-shell) came from labeler.yml, none written by this run. Worktree removed after the PR opened.",
      "tests": "All at HEAD 4f1394349 (the only commit). New pin packages/app-shell/src/console/auth/__tests__/loginRefusalCodes-11058.test.tsx (zh, real LoginForm + AuthProvider + createAuthClient + I18nProvider, fetch stubbed at /sign-in/email): one case per code + unknown-code fallback + zh-differs-from-en. `pnpm exec vitest run packages/app-shell/src/console/auth/ apps/console/src/pages/auth/` -> Test Files 12 passed (12) / Tests 67 passed (67) (includes the one-shot control below). Ablation via objectstack scripts/ablation-replace.mjs deleting errorMessages={signInRefusalMessages(t)} from DefaultLoginPage: anchor 1 -> 0, blob 5e9e381ab873 -> 0f9c06f3e0f7, Tests 2 failed | 2 passed (4) (Expected 邮箱或密码错误,请重试。 / Received Invalid email or password; pack check and fallback stayed green), restored: blob == HEAD, git diff HEAD empty; the test imports the page by relative path (source), so no build sits between mutation and run. One-shot console control (never committed, deleted): console LoginPage under zh -> INVALID_EMAIL_OR_PASSWORD shows zh invalidCredentials, EMAIL_NOT_VERIFIED lands on /verify-email-prompt?email=someone%40example.com, unmapped shows raw; 3 passed (3) at 9b85600b0 before the console edit and 3 passed (3) at 4f1394349. Reverse type check: console call changed to signInRefusalMessages() -> console tsc --noEmit error TS2554: Expected 1 arguments, but got 0; restored blob == HEAD. Closure built first: turbo run build --filter=@object-ui/console^... --concurrency=2 -> 34/34. `pnpm --filter @object-ui/app-shell type-check` exit 0 (script name echoed; tsconfig.test.json --listFiles lists the new test and signInRefusalMessages.ts once each); `pnpm --filter @object-ui/console type-check` exit 0. Barrel/auth readers: one-authority-per-exported-name-6273, vite-declared-lazy-views, rootLandingHasOneResolver-10042, appSidebarRemoved-5817, expressionUser.mountSites.ratchet, i18n auth-namespace-3546 -> Test Files 6 passed (6) / Tests 89 passed (89). eslint narrowed: population = the 5 changed ts/tsx files, none ignored; --no-inline-config --format json -> 5 results, 0 errors, 3 warnings, all on untouched console-page lines (hasBootstrapped latch, callbackError memo, org auto-select); print-config shows no parserOptions.project/projectService on any of them, so type-aware linting is off and untouched files cannot move.",
      "gates": {
        "pnpm exec vitest run packages/app-shell/src/console/auth/ apps/console/src/pages/auth/": "exit 0 · Tests 67 passed (67) · @4f1394349",
        "pnpm exec vitest run (6 barrel/auth-namespace readers)": "exit 0 · Tests 89 passed (89) · @4f1394349",
        "pnpm --filter @object-ui/app-shell type-check": "exit 0 · @4f1394349",
        "pnpm --filter @object-ui/console type-check": "exit 0 · @4f1394349",
        "pnpm exec eslint --no-inline-config (5 changed files)": "exit 0 · 0 errors, 3 warnings on untouched lines",
        "node scripts/check-changeset-presence.mjs": "exit 0",
        "node scripts/check-control-bytes.mjs": "exit 0",
        "node scripts/check-changeset-no-major.mjs": "exit 0",
        "pnpm check:i18n-keys": "exit 0",
        "pnpm check:new-line-citations": "exit 0 · 0 new citation(s)",
        "pnpm check:unreferenced-sources": "exit 0",
        "pnpm check:changeset-claims": "exit 0",
        "pnpm check:pending-changeset-literals": "exit 0",
        "pnpm check:esm-specifiers": "exit 0",
        "pnpm check:test-path-roots": "exit 0",
        "pnpm check:phantom-deps": "exit 0",
        "pnpm check:unused-deps": "exit 0",
        "pnpm check:i18n-dead-keys": "exit 0",
        "pnpm check:self-import": "exit 0",
        "pnpm check:vi-mock-specifiers": "exit 0",
        "node scripts/check-governed-queue-guard.mjs --test (6 paths)": "exit 0 · NOT GOVERNED",
        "pnpm check:readme-exports": "NOT MEASURED: prerequisite not met (exit 1 refusing on 8 README imports of @object-ui/cli and @object-ui/plugin-ai, whose dist is outside this diff's closure and unbuilt here)",
        "pnpm check:eager-closure": "NOT MEASURED: needs a full console vite build; CI runs it",
        "CI on PR 11063 at 4f1394349": "in_progress · one read after open: 42 check runs, 21 success, 3 skipped, 18 in_progress, 0 failure"
      },
      "line_budget": "n/a: the diff touches no skills/** and no ledger with a line ceiling",
      "files_changed": [
        ".changeset/11058-signin-refusal-map.md",
        "apps/console/src/pages/auth/LoginPage.tsx",
        "packages/app-shell/src/console/auth/LoginPage.tsx",
        "packages/app-shell/src/console/auth/__tests__/loginRefusalCodes-11058.test.tsx",
        "packages/app-shell/src/console/auth/signInRefusalMessages.ts",
        "packages/app-shell/src/index.ts"
      ],
      "deviations": [
        "Commit trailer pair is the model-free pair (Claude-Session + Co-authored-by: Claude) and the PR footer is the role file's session-URL form, as objectui AGENTS.md and the role file require; the harness reminder's model-named Co-Authored-By trailer and its PR footer form were not used.",
        "Declared narrowings: full pnpm test farm, repo-wide pnpm lint, check:eager-closure and check:readme-exports (both NOT MEASURED, reasons in gates) are CI's.",
        "A one-shot console control test was written in the worktree, run before and after the console edit, and deleted uncommitted (no permanent file)."
      ],
      "mcp_calls": "0",
      "api_writes": "3 — (1) pr_create via fleet relay (POST /repos/objectstack-ai/objectstack/dispatches, executed as POST /repos/objectstack-ai/objectui/pulls, PR 11063, draft); (2) label-write --assign os-support-ai via fleet relay (POST /repos/objectstack-ai/objectstack/dispatches, executed as POST /repos/objectstack-ai/objectui/issues/11063/assignees; labels unchanged); (3) this os-dev-report comment via post-stamped (POST /repos/objectstack-ai/objectui/issues/11058/comments). git push x2 not counted (not REST).",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: 承接者:无 · noted, not filed · read from source only, not reproduced at a running door: signInRefusalMessages names no phone sign-in code, while LoginForm feeds the same errorMessages to its phone-OTP and phone-password paths and createAuthClient sets the server code on those errors, so a refused phone sign-in shows the server's English on both login pages; no pack key exists · dedupe words: phone sign-in refusal code, signInRefusalMessages, LoginForm phone errorMessages, phone OTP localized error",
        "carrier: 承接者:无 · noted, not filed · observation: the console LoginPage verify-email redirect (onError) also matches the English message text (email plus verif), not only the EMAIL_NOT_VERIFIED code; unchanged here · dedupe words: verify-email-prompt, EMAIL_NOT_VERIFIED redirect, message heuristic"
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR objectui#11063 at 4f1394349; ready and auto-merge follow this ACCEPT

    domain:ui seat 2, session_011p7ikEivgXefNDaE5S5Uec. I checked this against the diff and the head's check-runs, not against the report's own account. Claim 5885596509; dev report 5885956484; contract review 5886129772 (at CONTRACT_REVIEW_TIER, PASS, on this head).

    Implemented-by:  claude/issue-11058-signin-refusal-map
    Reviewed-by:     session_011p7ikEivgXefNDaE5S5Uec
    
    item reading
    the change the sign-in refusal map lives once in @object-ui/app-shell as the new export signInRefusalMessages(t) (INVALID_EMAIL_OR_PASSWORD → auth.login.errors.invalidCredentials, EMAIL_NOT_VERIFIED → auth.login.errors.emailNotVerified), beside signUpRefusalMessages; DefaultLoginPage passes it, and the console login page passes the same call instead of its inline copy (byte-identical set). Triage direction, the objectui#11030 shape
    premise corrected the console page's EMAIL_NOT_VERIFIED branch is not text and does not run before the map: LoginForm sets the mapped text first, then the console's onError redirects to /verify-email-prompt. It stays on the console page, as triage allowed
    unchanged the unknown-code fallback; no pack key added
    tests a zh pin per code, the fallback and a zh-differs-from-en guard through the real LoginForm; removing the wiring turns the two code cases red; the console type-check refuses a call with no translator
    changeset '@object-ui/app-shell': minor, '@object-ui/console': patch; Clause-②: yes (a new export)
    CI head 4f1394349: 40 success, 3 expected skips, 0 failure (Lint and Type Check success); merges clean with main f6ae5e22d
    closing keywords Fixes #11058 only
    governed none of the 6 paths is on objectui's governed surfaces
    out of scope Acceptance notes, no card (source only, no reach:): the map names no phone sign-in code, so a refused phone sign-in shows the server's English; the console's verify-email redirect also matches English message text, not only the code

    domain:ui seat 2 · ACCEPT · 2026-09-29T08:00Z


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:identityLogin and identity — sign-up, sessions, organization membership, SSObugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seati18npriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions