Repository navigation
fix(app-shell): turning on Require MFA on an organization shows the grace period once - #30592
Merged
Merged
Conversation
…d notice once An accepted require_mfa turn-on on sys_organization now answers a save notice from the server naming the grace period in force. The record form no longer appends its own console.organizationMfa.nowRequired line (which names the default 7 days) when the answer's notice is that server notice, recognized by its opening sentence in the four languages the server writes it in. No notice, or another hook's notice, keeps the console line. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L6bhgVfPeFZkN1FP93imKU
An organization save that turns require_mfa on and whose answer carries the server's MFA notice toasts that notice alone; with no notice, or another hook's notice, the console line stays. Pinned in the record-save toast harness, so the AppContent wiring (answerNotice) is under test too. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L6bhgVfPeFZkN1FP93imKU
Contributor
Author
|
domain:ui#4 · os-sales · session_01L6bhgVfPeFZkN1FP93imKU 维护者速读
席位核对 — ACCEPT · head 9dee7aa
Generated by Claude Code |
This was referenced Nov 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #30565
Clause-②: no
Metadata-protocol: none
维护者速读
27b0bc79上用单元复现:提示两行,一行 3 天、一行 7 天)。ui/packages/app-shell/src/console/organizationMfaNotices.ts的SERVER_MFA_NOTICE_OPENINGS与isServerMfaNotice;AppContent.tsx的handleRecordFormSuccess里多传的answerNotice: claimed?.notice。pnpm --dir ui exec vitest run packages/app-shell/src/console/__tests__/organizationMfaNotices-30295.test.tsx packages/app-shell/src/console/__tests__/AppContent.recordSaveOneToast-27999.test.tsx,预期 26 个用例全绿。What changes
@object-ui/app-shell,organizationMfaSavedNotice(console/organizationMfaNotices.ts) takes one more optional input,answerNotice: the save answer'snoticeas the record form's claim took it. When that notice is the server's own MFA notice, the function returnsundefined, so the console adds noconsole.organizationMfa.nowRequiredline. Everything else it judged before (object, stored value, saved value) is unchanged.AppContent.tsx,handleRecordFormSuccesspassesanswerNotice: claimed?.noticeto it. The join below (claimed.notice+ the console line) is unchanged: with no console line it hands the claim's feedback through, so the toast carries the server's notice once.en,zh-CN,ja-JP,es-ES; plugin-auth'sORGANIZATION_MFA_REQUIRED_NOTICE_COPY). The N-day and 0-day sentences open with the same one, so four constants cover all of them. A bare "a notice is there" check is not enough: the answer carries ONE notice, the last one a hook or a flow'ssave_noticenode on the write set (WRITE_ANSWER_NOTICE_DESCRIPTIONin the protocol, "when more than one call sets it, the LAST one wins"). The MFA guard sets its notice atbeforeInsert/beforeUpdatepriority 15, so any later hook replaces it. On that save a presence check would drop the only sentence that tells the administrator who will be blocked. The wrong direction for this rule is also the safe one: if the server's wording ever changes, the console shows both lines again, never neither..changeset/30565-organization-mfa-notice-once.md,@object-ui/app-shellpatch.Tests
A new top-level
describeinui/packages/app-shell/src/console/__tests__/organizationMfaNotices-30295.test.tsx(this module's existing harness):en3 days,en0 days,zh-CN3 days,ja-JP0 days,es-ES3 days. Each fixture was checked byte-identical toORGANIZATION_MFA_REQUIRED_NOTICE_COPY[locale](days)evaluated from the server source at this head.Sent to your manager for approval): the console line too.A new top-level
describeinui/packages/app-shell/src/console/__tests__/AppContent.recordSaveOneToast-27999.test.tsx(the record-save toast harness, a realAppContentmount; the harness gains asys_organizationobject, afindOneon its adapter stub answering the stored row withrequire_mfa: false, andsaveFromnow checks the overlay edits the object the write names). An edit of organizationorg_1savesrequire_mfa: true:noticeis the server's English 3-day notice (the 30295 fixture): ONE success toast,Organization "Acme" updated, whose description is the server notice alone; the stored row was read (findOne('sys_organization', 'org_1')).console.organizationMfa.nowRequiredinen, which names 7 days).Acceptance notes
copyLocaleFor). The console ships ten locales. A console inde,fr,ko,pt,ruorarused to show the English server notice followed by its own localized line. It now shows the English server notice only. Adding those six languages to the server copy belongs to the server lane (out of scope here).AppContent.tsx(answerNotice: claimed?.notice) is pinned on a mountedAppContentin the shared record-save toast harness (see Tests). Deleting that line reds the server-notice case (ablation 3).Verification
Base
27b0bc79, head9dee7aa4. The fix is8aa05756;9dee7aa4adds only the mount-level pin.Premise, tests, ablation
AppContent's join verbatim throughtoastRecordSavewith theencatalogue and the server's 3-day notice): one success toast whose description has 2 lines, containing both "3 days" and "7 days". The same probe on the fix: 1 line, "3 days" only.pnpm --dir ui exec vitest run --maxWorkers=2 packages/app-shell/src/console/__tests__/organizationMfaNotices-30295.test.tsxon the head: Test Files 1 passed (1), Tests 14 passed (14).pnpm --dir ui exec vitest run --maxWorkers=2 packages/app-shell/src/console/__tests__/AppContent.recordSaveOneToast-27999.test.tsx packages/app-shell/src/console/__tests__/organizationMfaNotices-30295.test.tsxon9dee7aa4: Test Files 2 passed (2), Tests 26 passed (26).pnpm --dir ui exec vitest run --maxWorkers=2 packages/app-shell/src/console/__tests__/under the verify lock on9dee7aa4: Test Files 75 passed (75), Tests 619 passed (619), VERDICT command-exit 0 (616 on8aa05756).scripts/ablation-replace.mjs, deleteif (isServerMfaNotice(input.answerNotice)) return undefined;, anchor x1 to x0): 5 failed / 9 passed, the five server-notice cases red, the no-notice and other-notice controls green. Restored: blob63b87c8cequals HEAD,git diff HEADempty.if (input.answerNotice) return undefined;): 1 failed / 13 passed, the other-hook-notice case red. Restored: blob equals HEAD,git diff HEADempty.9dee7aa4, deleteanswerNotice: claimed?.notice,inAppContent.tsx, anchor x1 to x0, blobb8669035toadc800b5): 1 failed / 11 passed in the 27999 harness, the server-notice case red, both CONTROLs and the nine earlier cases green. Restored: blobb8669035equals HEAD,git diff HEADempty.Gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon head9dee7aa4(5 paths) derived the same 35 commands as on8aa05756; each was re-run on9dee7aa4and its exit code recorded before any pipe:node scripts/check-adr-0087-registration.mjs --base origin/main:: exit 0node scripts/check-adr-0087-registration.mjs --self-test:: exit 0node scripts/check-changeset-no-major.mjs --base origin/main:: exit 0node scripts/check-closing-keyword-parity.mjs:: exit 0node scripts/check-closing-keyword-parity.mjs --self-test:: exit 0node scripts/check-comment-mask-corpus.mjs:: exit 0node scripts/check-empty-changeset.mjs --base origin/main:: exit 0node scripts/check-empty-changeset.mjs --self-test:: exit 0node scripts/check-sdui-manifest.mjs:: exit 0node scripts/check-sdui-manifest.mjs --self-test:: exit 0node scripts/pm/release-rehearsal-clone.mjs --self-test:: exit 0node scripts/release-pending-publish.mjs --self-test:: exit 0pnpm --dir ui exec vitest run scripts/:: exit 0pnpm --filter @objectstack/spec run check:duration-unit-keys:: exit 0pnpm check:changeset-gate-self-tests:: exit 0pnpm check:closed-ceremony-text:: exit 0pnpm check:cross-package-test-inputs:: exit 0pnpm check:dispatcher-error-vocabulary:: exit 0pnpm check:driver-memory-census:: exit 0pnpm check:engine-double-contract:: exit 0pnpm check:gitlink-declared:: exit 0pnpm check:nul-bytes:: exit 0pnpm check:published-files:: exit 0pnpm check:query-options-erasure:: exit 0pnpm check:refd-timer-probe:: exit 0pnpm check:registry-log-declared:: exit 0pnpm check:rest-log-spy-declared:: exit 0pnpm check:skill-identifier-liveness:: exit 0pnpm check:test-source-alias:: exit 0pnpm check:tier-file-adoption:: exit 0pnpm check:type-check-coverage:: exit 0pnpm check:type-check-debt:: exit 0pnpm check:undeclared-dep-imports:: exit 0pnpm check:watch-hint-literal:: exit 0pnpm check:where-matcher:: exit 0node scripts/pm/dispatch-gates.mjs --ran ran.list --repo objectstack-ai/objectstackon9dee7aa4:: exit 0, "35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN".Also:
pnpm --dir ui run check:spec-symbols:: exit 0node scripts/check-new-cross-file-line-citations.mjs(ui) :: exit 0, 0 new citationsnode scripts/check-control-bytes.mjs(ui) :: exit 0pnpm exec turbo run type-check --filter=@object-ui/app-shellunder the verify lock on9dee7aa4(cache miss on@object-ui/app-shell:type-check, bothtsc --noEmitandtsc -p tsconfig.test.json, so the test files are compiled) :: VERDICT command-exit 0, 68 tasks successfuleslinton the changed source and test files :: exit 0, 0 errors (the 27999 harness: 0 problems)CI runs the rest.
Human Minimum
packages/specholds no runtime logic. (no schema touched)pnpm lintpasses. (eslint on the changed source and test files: 0 errors; its warnings are onAppContent.tsxlines this PR does not change)main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed. (not touched)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.维护者速读block the os-dev contract asks for)Generated by Claude Code