Skip to content

platform-objects: Create User's result dialog always says "Copy the temporary password now", though a typed password returns none to copy #24936

Closed

Description

@objectstack-fleet

Filing gate ③ a task the maintainer set: objectstack-ai/hotcrm#2207, the maintainer's browser round on ObjectStack 18.0.0 (「hotcrm 升级到 objectstack 18.0 然后重新安排一轮浏览器测试」). Each defect gets its own card, by the maintainer's ruling 「按照按照具体的issue单独提交卡片,不受数量限制。」 (recorded on objectstack-ai/hotcrm#2188, 6283467378). This is finding F-02 of track 2 (the Setup pass as the system administrator), by the cloud tester session_01BkRPwuAufrFwoEEfuigDm9. It was measured on HotCRM main 16c28664 with @objectstack/* 18.0.0 (framework 06cab4849, console objectui 616df6598b42), in Chromium at 1440×900 on a locally booted, seeded install. The evidence is on the branch claude/qa-v18-setup-pass at 4d7cc467d (REPORT.md), which is never merged. Filed by the repo:hotcrm seat 2 (os-support-ai, session session_01KqkTQNLcxVc588eZpJmp1r). ⛔ Not a claim. Grade: triage's.

Reader (who acts): objectstack triage routes it.

The finding, as measured

  • Persona / URL: dev admin, Setup → Users → Create User.
  • Steps: enter an email, a name and a password; Confirm.
  • Expected: the field's own label, "Password (leave empty to generate)". Only a generated password needs showing once, as the generated case does ("Temporary Password ••••").
  • Actual: the dialog reads "User Created — Copy the temporary password now — it is shown only once and never stored." It shows only the email, and its button is "I have saved this password". No password was generated, so there is nothing to copy, and the admin is left unsure whether the typed password was used.
  • Evidence: 07-people-users-created.png (typed), 07-people-users-created-generated-redacted.png (generated, for comparison).
  • Reach: every admin who sets a user's first password.

Seat review (source at 18.0.0, 06cab4849)

  • The copy is static metadata: packages/platform-objects/src/identity/sys-user.object.ts:263-264 (description: 'Copy the temporary password now — it is shown only once and never stored.', acknowledge: 'I have saved this password').
  • The renderer is right: it skips temporaryPassword when the response has none (:268), so only the email shows.
  • ActionSchema.resultDialog (packages/spec/src/ui/action.zod.ts:1460) has no per-outcome copy.
  • The sibling set_user_password in the same file already hedges: "If a temporary password was generated, copy it now — it is shown only once and never stored." (:326).
  • Not plugin-auth and not the objectui renderer (the tester's guess). Unchanged on main.

Dedupe

Method: every objectstack-ai/objectstack issue title (every state, #1–#24932) and every objectstack-ai/objectui issue title (#7–#13268), listed through the repo-scoped issues?state=all endpoint (refreshed with since=2026-10-19) and matched case-insensitively. The search API is refused for this session.

  • Related, closed: objectstack#22821 (same action; fixed the ignored "Generate" checkbox, left this copy as it was).
  • Different: objectstack#24758 (the password params are clear-text inputs); objectstack#3031; objectstack#3260.
  • New.

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 23 (p3 only, by the maintainer's order 「你后续只处理 p3」) · 2026-10-21T07:03Z · p3, domain:engine (triage's grade), filed by repo:hotcrm seat 2 from objectstack-ai/hotcrm#2207's v18 Setup pass, F-02. When an administrator creates a user and types the password, the result dialog still says "Copy the temporary password now — it is shown only once and never stored" and offers "I have saved this password", though there is no generated password to copy. The administrator is left unsure whether the typed password took.
    Session: session_01JtSQQ3EWsbNPzyYMug1tXy (the dispatching seat; the dev runs as its own cloud session, named in the dispatch comment)
    Account: os-project-manager (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-24936-create-user-dialog-copy
    Worktree: objectstack-issue-24936
    Domain: domain:engine
    Seat: domain:engine#1 (seat post #6367)
    File surface:

    • Measured first:
      • the create_user action's resultDialog in packages/platform-objects/src/identity/sys-user.object.ts (description, acknowledge). Its sibling set_user_password already hedges: "If a temporary password was generated, copy it now — it is shown only once and never stored.";
      • what the server returns for a typed and for a generated password (temporaryPassword present only when minted), and how the dialog renders each (objectui, read only);
      • every pin and translation of the two strings: the generated en.objects.generated.ts, the locale bundles under packages/platform-objects/src/apps/translations/, and the fixtures in packages/cli/test/i18n-extract.test.ts and packages/spec/src/system/i18n-resolver.test.ts. Say whether each fixture quotes this object or carries its own copy.
    • sys-user.object.ts, the create_user resultDialog text only: the dialog's sentence and its button read true for both outcomes, in the hedged shape set_user_password already uses. Regenerate the generated bundle with the repo's tooling, and translate by the repo's rule.
    • Pins: the dialog text, for both outcomes where the metadata allows it. Ablation: revert, and the pin goes red.
    • The changeset: patch for @objectstack/platform-objects.

    ⛔ Not in scope:

    Container & model: S, mode:cloud (one metadata sentence, its bundles and pins), model: TIER_DEFAULT (this run's dispatch-gates.mjs --tier: "no path-derived mandate")
    Clause-②: no (text only: the create-user result dialog's sentence and button; no param, response, status, outcome or export moves)
    Responsibility: an administrator who types a new user's password is told to copy a temporary password that does not exist | the create_user result dialog's copy assumes the generated case | every administrator who sets a user's first password in Setup
    Thread-read: none
    Serial constraints cleared: the 12 open PRs' file lists and the pm:dispatched claims were read at this claim, on origin/main 2b1382a5b3. No open PR touches sys-user.object.ts or packages/platform-objects/src/apps/translations/. No held claim names that file.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    Dispatch · domain:engine seat 1 · session_01JtSQQ3EWsbNPzyYMug1tXy · 2026-10-21T07:06Z: mode:cloud. The dev session is session_01MZw2Leqg5M8ZH9pKpMh9jS. It builds at the default tier on branch claude/issue-24936-create-user-dialog-copy, under claim 6310152795.

    • Read first:
      • what create_user returns for a typed and for a generated password, and how the dialog renders each;
      • every pin and translation of the dialog's sentence and button.
    • What lands:
      • the create_user result dialog's sentence and button read true for both outcomes, in the hedged shape set_user_password uses;
      • the regenerated bundle and translations;
      • a metadata pin with an ablation, and a patch changeset for @objectstack/platform-objects.
    • Moving pins: any pin of this object's text that turns red moves in the same PR, test files only. Those in domain:cli's or domain:spec's packages are named for the seat to declare before the queue.
    • Not built: a per-outcome spec key, the server handler, objectui, platform-objects: the sys_user page's Security tab shows the viewer's own "your account" sections, empty, on every other user's record #24938.
    • Owed: the seat's review of record before the queue.

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24936,
      "status": "done",
      "branch": "claude/issue-24936-create-user-dialog-copy",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/25081",
      "session": "session_01MZw2Leqg5M8ZH9pKpMh9jS (dispatched by session_01JtSQQ3EWsbNPzyYMug1tXy, domain:engine seat 1, post #6367)",
      "premise_still_valid": true,
      "summary": "Read first, before any edit. plugin-auth admin-user-endpoints.ts returns temporaryPassword only when resolved.generated, so a typed password returns {user, placeholderEmail, mustChangePassword, membershipCreated} and no temporaryPassword. The dialog's fields comment says absent paths are skipped. objectui is not in this container, so the renderer was not read here; the claim rests on the card's seat review. Census of the two strings: sys-user.object.ts (source); en.objects.generated.ts (generated); zh-CN, ja-JP and es-ES objects.generated.ts (hand-written leaves, no source-hash entry). packages/cli/test/i18n-extract.test.ts carries its OWN set_password fixture with different text, not a pin of this object. packages/spec/src/system/i18n-resolver.test.ts carries its OWN inline createUser object and zh-CN bundle and imports nothing from platform-objects, so it is not a pin either. Neither moved. Built: create_user resultDialog description = 'If a temporary password was generated, copy it now — it is shown only once and never stored.' and acknowledge = 'Done', the same sentence and button as set_user_password. en was regenerated with check-i18n-bundles --write. The three locales reuse set_user_password's existing translations. A new pin file was added, plus a patch changeset. Params, bodyExtra, handler, response, title and fields are unchanged.",
      "tests": "head 4fdd4999b. pnpm --filter @objectstack/platform-objects typecheck: exit 0 (lock VERDICT command-exit 0). pnpm --filter @objectstack/platform-objects test: exit 0, Test Files 84 passed (84), Tests 1243 passed (1243), run both before and after the full build. pnpm --filter @objectstack/core test:repo: exit 0, Test Files 6 passed (6), Tests 82 passed (82). New pin create-user-result-dialog-copy.test.ts: 4/4. Ablation 1 via scripts/ablation-replace.mjs on sys-user.object.ts, old sentence and button restored: anchor 1->0, blob bc6b1792->3f5199d7, 2 failed | 2 passed; restore blob == HEAD bc6b1792, git diff HEAD empty. (The first attempt was refused before any write: ANCHOR AMBIGUOUS x2, exit 3, mutation never landed. It was re-run with a longer anchor.) Ablation 2 on zh-CN.objects.generated.ts, old leaves restored: blob c6d8953c->5326f33a, 1 failed | 3 passed; restore blob == HEAD, git diff HEAD empty. The pin imports src directly (./index.js and relative bundle paths), with no dist in the resolution path, so no rebuild was needed per leg. Full build pnpm exec turbo run build --concurrency=2: VERDICT command-exit 0. check-i18n-bundles --write: first run exit 3 (CLI not built); after building its named closure, exit 0, and only en.objects.generated.ts changed.",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack (no paths) at 4fdd4999b derived 66 families, all run with exit codes captured before any pipe: 65 exit 0 on the first pass. pnpm check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET, no dist/), re-run after the full build: exit 0. --ran with ' :: exit N' annotations: '66 derived famil(ies) accounted for — 66 run, 0 NOT-MEASURED (a DERIVED zero — all 66 recorded an exit code and none of them is 3)', exit 0. Before the gates the clone was deepened with git fetch --shallow-since=2026-07-13. origin/main re-fetched before the PR: still 2b1382a5b, merge 'Already up to date'. Build and typecheck were re-run after it (see tests). The PR's base has since moved to c0ae356ce; CI check-runs are in_progress or not yet read and NOT cited here. The PM reads CI convergence. check:nul-bytes exit 0.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "line_budget": "none set. Diff +/- per file: .changeset/24936-create-user-dialog-copy.md +9/-0; packages/platform-objects/src/apps/translations/en.objects.generated.ts +2/-2; es-ES.objects.generated.ts +2/-2; ja-JP.objects.generated.ts +2/-2; zh-CN.objects.generated.ts +2/-2; packages/platform-objects/src/identity/sys-user.object.ts +5/-2; packages/platform-objects/src/identity/create-user-result-dialog-copy.test.ts +70/-0. Total +92/-10 over 7 files.",
      "files_changed": [
        ".changeset/24936-create-user-dialog-copy.md",
        "packages/platform-objects/src/apps/translations/en.objects.generated.ts",
        "packages/platform-objects/src/apps/translations/es-ES.objects.generated.ts",
        "packages/platform-objects/src/apps/translations/ja-JP.objects.generated.ts",
        "packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts",
        "packages/platform-objects/src/identity/sys-user.object.ts",
        "packages/platform-objects/src/identity/create-user-result-dialog-copy.test.ts"
      ],
      "deviations": [
        "No pin in another lane moved. packages/cli/** and packages/spec/** are untouched, so the seat has no lane declaration to make.",
        "Commit trailers: the harness attribution reminder asked for a Co-Authored-By trailer naming the model. AGENTS.md and os-dev.md require the model-free pair (Claude-Session + Co-authored-by: Claude), and the pre-push hook enforces it, so the model-free pair was used. The repo rule wins.",
        "objectui's renderer was not read: the sibling repo is not in this container, and the GitHub scope is objectstack only. Recorded as NOT MEASURED, and also in the PR's Acceptance notes.",
        "Worktree cleaned up after the PR (node_modules removed, git worktree remove succeeded with a clean tree)."
      ],
      "mcp_calls": "4 — read-only GitHub MCP: mcp__github__issue_read x3 (#24936 get, #24936 get_comments, #22821 get), mcp__github__pull_request_read x1 (#25081 get, body read-back). No MCP write tool.",
      "api_writes": "3 — git push to claude/issue-24936-create-user-dialog-copy (empty-branch probe plus two commit pushes, one branch); fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/pulls draft + POST /issues/25081/assignees, run 39564370891, read-back 5236/5236 bytes identical, assignees os-project-manager); fleet-write relay comment on #24936 (this os-dev-report).",
      "open_questions": [
        {
          "question": "Wording of the create_user resultDialog (settled by the dev, by the four axes)",
          "options": [
            "A: reuse set_user_password's sentence and 'Done' verbatim",
            "B: new copy, e.g. 'User created. If a temporary password was generated…' plus 'Close'",
            "C: a per-outcome spec key (out of scope, domain:spec)"
          ],
          "recommendation": "A, chosen. Real need: true in both outcomes, and the button claims no saved password. Long-term: one hedged sentence for the two dialogs with the same response shape. AI-proof: the pin ties both dialogs in all four locales. No scope growth: the translations already exist and no spec key is added."
        }
      ],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:engine seat 1 · session_01JtSQQ3EWsbNPzyYMug1tXy · 2026-10-21T08:53Z

    Probe Reading
    Review TIER_DEFAULT. Record 6311080671 PASS on 4fdd4999b9. ACCEPT 6311418704. Not governed.
    Queue It entered the merge queue at 2026-10-21T08:22Z and left it merged at 2026-10-21T08:51Z. No gh-readonly-queue/main/pr-25081-* branch remains.
    origin/main 5d2c5a1a8a is on origin/main, one squash commit carrying PR #25081's 7 files, +92 / −10.
    Card Closed completed through Fixes #24936; pm:dispatched is cleared.

    What main now holds:

    • Create User no longer asks an administrator to save a password it never showed. The result dialog reads "If a temporary password was generated, copy it now — it is shown only once and never stored." with a "Done" button. Before, it said "Copy the temporary password now — it is shown only once and never stored." and "I have saved this password", even when the administrator had typed the password.
      • After a typed password, the dialog shows the email and this sentence.
      • After a generated one, it also shows the password with its copy control.
    • The same in every locale: zh-CN, ja-JP and es-ES reuse the "Set password" dialog's existing translations, so the two dialogs, whose responses have the same two outcomes, read alike.
    • Unchanged: the action's params, the server handler and its response, and the fields the dialog lists.
    • Shipped as: patch of @objectstack/platform-objects, Clause-②: no (text only: …).

    Beside it: no file outside packages/platform-objects moved. The cli and spec i18n tests carry their own fixtures of a similar sentence and needed no change.

    The dev session session_01MZw2Leqg5M8ZH9pKpMh9jS is archived.


    Generated by Claude Code

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

Metadata

Metadata

Labels

area:identityLogin and identity — sign-up, sessions, organization membership, SSObugSomething isn't workingdomain:enginepriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions