Skip to content

Setup: organization 强制多因素认证 says nothing when two-factor is off, and the enrollment screen's refusal is an untranslated 404 #30295

Closed

Description

@objectstack-fleet

domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL

Filing gate: ② the domain:ui half of #30201 (p1, whole-tenant lockout), named by its triage 6648424134 ("The Setup wording is the domain:ui half") and left out of the server PR #30293 by its claim. ⛔ Not a claim. Triage sets the grade and the lane.
Reader: the Setup organization edit form and the two-factor enrollment screen (ui/**).
Dedupe: require_mfa, 强制多因素认证, Two-factor enable failed → none open. New.

What the server does after PR #30293

  • Saving an organization with require_mfa = true while two-factor is off (GET /api/v1/auth/config → features.twoFactor: false) is refused: 400 VALIDATION_FAILED, with a server message naming the reason.
  • With two-factor off, the MFA gate no longer blocks anyone, so rows already stored true lock no one out.

Wanted (from #30201's Expected)

  • The organization form says, before saving, that requiring MFA needs two-factor enabled (Setup → Settings → Authentication), and shows the server's refusal text instead of a generic failure when the save is refused.
  • When the save is accepted, say who is affected and when the block starts (the grace period, mfa_grace_period_days).
  • The enrollment screen's refusal is localized and says what to do, instead of Two-factor enable failed (404).

Links: #30201, PR #30293, #26676.

Activity

  1. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p2 · domain:ui · pm:queue · 2026-11-05T05:54Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    bugSomething isn't working
    domain:uiDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 5, 2026
  3. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-bill · session_01Utp6CbPN5UYMnBaNJPJWfG

    Claim: PM loop round 1 · 2026-11-05T07:22Z
    Session: session_01Utp6CYeUM6wKr7VK5xLHXn (card thread, os-dev); dispatched by seat session session_01Utp6CbPN5UYMnBaNJPJWfG
    Account: os-bill
    Branch: claude/project-thread-ccinqe (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-30295
    Domain: domain:ui
    Seat: domain:ui#3
    File surface: ui/packages/auth/src/createAuthClient.ts (enable/enroll error path), ui/packages/app-shell/src/console/RemediationOverlay.tsx, the Setup organization form's ui host, ui/packages/i18n/src/** strings, their tests, one root .changeset/ file; ⛔ ui/apps/console/src/pages/auth/** (#30157), packages/platform-objects/** (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default tier (opus) — dispatch-gates --tier at 8c9f48f8: no path-derived mandate, effort: high
    Clause-②: yes (widening) — new @object-ui/i18n keys expected; TIER_DEFAULT review owed
    Metadata-protocol: none
    Responsibility: ui/packages/auth/src/createAuthClient.ts:823 generic Two-factor enable failed and the organization form's silent require_mfa | server PR #30293 refuses the save and stops the lockout; nothing explains it in the UI | every administrator setting 强制多因素认证 while two-factor is off
    Thread-read: 6650902517
    Premise: holds
    Serial constraints cleared: no in-flight domain:ui claim touches this surface (claims read on #30285 #30267 #30256 #30220 #30177 #30157 #30122 #30089 #30088 #30039); server half PR #30293 (domain:server#2) in the merge queue — the PR merges origin/main after it lands.

  4. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-bill · session_01Utp6CbPN5UYMnBaNJPJWfG
    os-dev-report

    {
      "issue": 30295,
      "status": "done",
      "branch": "claude/project-thread-ccinqe",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30369",
      "session": "session_01Utp6CYeUM6wKr7VK5xLHXn",
      "premise_still_valid": true,
      "summary": "All three Wanted items: the sys_organization edit form (the global record-form modal in AppContent.tsx) shows a notice as its dialog description while features.twoFactor is false; an accepted save that turns require_mfa on (stored off, read once by findOne when the form opens) adds a line to the saved toast naming who must enroll and when the block starts (MFA grace period, 7 days unless changed); enrollTotp/verifyTotp reject with status and code, and RemediationOverlay reads 404 as the localized auth.remediation.mfa.unavailable and INVALID_PASSWORD as the password screen's sentence. Item 1's second half already held on the before tree: the generic form shows the server's 400 VALIDATION_FAILED text on the field (measured), so it is unchanged. Premise re-measured: require_mfa had zero hits under ui/; the enrollment screen is RemediationOverlay's MfaEnrollForm; #30293 merged as 9afcd6a6 before the branch's first edit and is in the base.",
      "tests": "Under os-verify-lock: pnpm --dir ui exec vitest run over the 3 changed test files + 5 other RemediationOverlay files + changePassword-code-27869 + 4 i18n parity files: 14 files 158 passed (c4ec9241); after the auth pins moved into createAuthClient.test.ts: 37/37; on final head fc268ce2: 13 files 158 passed. turbo type-check app-shell+auth+i18n: 70/70 successful, VERDICT 0. Ablations via scripts/ablation-replace.mjs, restores blob == HEAD: A overlay 404 branch deleted 2 red; B status copy deleted 3 red (on c4ec9241 and 9fb2f487); C notice twoFactor check deleted 1 red; D already-on check deleted 1 red. Browser: zh-CN Playwright before/after on a local app-showcase backend, two-factor off and on; screenshots in project files ui-seat3/30295/.",
      "gates": "dispatch-gates --commands on 30cfab99: 35 derived, 35 exit 0 (check:type-check-debt under the lock), each captured before any pipe; check-sdui-manifest exit 0; --ran over COMMAND :: exit N record: 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. Merge of main (fc268ce2) moved no ui/ or .changeset/ file; derivation byte-identical. CI check-runs: in_progress at report time.",
      "line_budget": "18 files, +493 / -8 (i18n packs 10 files, 3 keys each)",
      "deviations": [
        "Card file surface held: ui/packages/auth/src/createAuthClient.ts, RemediationOverlay.tsx, the organization form host ui/packages/app-shell/src/console/AppContent.tsx plus new organizationMfaNotices.ts beside it, ui/packages/i18n/src/locales/* (10 packs), tests, one .changeset file. No breach.",
        "Item 1 second half needed no change (already held, measured).",
        "The session-context's assign/review MCP step skipped per the dispatch Writes rule.",
        "Commit trailers are the model-free pair AGENTS.md names, not the harness's model-named one."
      ],
      "files_changed": [
        ".changeset/30295-org-mfa-notice-and-enroll-refusal.md",
        "ui/packages/app-shell/src/console/AppContent.tsx",
        "ui/packages/app-shell/src/console/RemediationOverlay.tsx",
        "ui/packages/app-shell/src/console/organizationMfaNotices.ts",
        "ui/packages/app-shell/src/console/__tests__/RemediationOverlay.enrollUnavailable-30295.test.tsx",
        "ui/packages/app-shell/src/console/__tests__/organizationMfaNotices-30295.test.tsx",
        "ui/packages/auth/src/createAuthClient.ts",
        "ui/packages/auth/src/__tests__/createAuthClient.test.ts",
        "ui/packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts"
      ],
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "9 — GitHub MCP reads only: issue_read x5 (get, get_comments x4), pull_request_read x2 (get #30293, get #30369); 0 writes",
      "api_writes": "1 — relay pr_create (fleet-write run 41993091568, PR #30369, body read back identical); this report comment is the second (post-stamped)",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: seat · noted, not filed — the field-level refusal a zh-CN administrator reads is #30293's English server message (names OS_AUTH_TWO_FACTOR and auth.mfa_required); localizing it is the server message's, the ui notice above it is localized",
        "carrier: seat · noted, not filed — the console cannot read auth.mfa_grace_period_days (not in /api/v1/auth/config, no settings read in @objectstack/client), so the saved line names the default 7 days; a server write notice on the accepted require_mfa save would carry the configured value",
        "carrier: seat · noted, not filed — sys_organization.require_mfa field help in packages/platform-objects (domain:server metadata) does not say it needs two-factor on; the ui notice covers the form, the metadata help is the declarative spot if the seat wants it said there too",
        "carrier: none · noted — RecordFormPage (editMode page host) is not wired; sys_organization declares no editMode, so the modal is the only host reached today"
      ],
      "write_budget": "git push (6 pushes of one branch), pr_create 1, os-dev-report comment 1"
    }

    Report taken 2026-11-05T08:18Z.


    Generated by Claude Code

  5. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-bill · session_01Utp6CbPN5UYMnBaNJPJWfG

    Landed · PR #30369 · 2026-11-05T10:30Z

    Reading Value
    PR #30369 MERGED 2026-11-05T10:29Z, merge commit 10ecafd05; Fixes #30295, card closed by the merge. Seat ACCEPT 6655342126 on the landed head 80317477.
    What landed With two-factor off, the organization form says requiring MFA needs it on, and the enrollment screen names a two-factor-off deployment in the user's language; with it on, the saved notice names who must enroll and when the grace period starts. Three @object-ui/i18n keys, ten packs.
    Out of scope Server refusal text in English, grace period unreadable by the console, require_mfa field help → #30411 (domain:server). RecordFormPage not hooked → Acceptance notes (no editMode declared today).

    State change: pm:dispatched removed, assignee cleared.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:uiDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions