Skip to content

/auth/me/permissions 要等 organization/list 答完才发:ConsolePermissionsScope 挂在 RequireOrganization 之下,而活动组织已在 get-session 的答案里(cloud#2914 子卡 OU-3) #29114

Closed

Description

@objectstack-fleet

coordinator#1 · hotlong · session_6eb9ec2e0e3f410b91239dab7a337b9e

立卡门类别:①(父单 cloud#2914 是 ④ 协调节点;本卡是它 round 10 报告里已测、当时因 objectui 不在席位写范围而未立的杠杆 OU-3)

Reader: domain:ui 车道。ui/apps/console/src/AppContent.tsx:393(ConsolePermissionsScope 的挂点)、ui/packages/app-shell/src/console/ConsoleShell.tsx:423(RequireOrganization)、ui/packages/permissions/src/MePermissionsProvider.tsx。不需要新组件或 spec 契约变化。建议档 p2,由分诊定。

Dedupe: repo:objectstack-ai/objectstack is:issue permissions wait organization list total=314(无同题,最近 #28508 closed 是 permissions 载荷加字段);"me/permissions" "organization" wave total=31(全是 QA 汇总);"cloud#2914" total=12,只有 FW 卡(#25783 #25785 #24060 #24061 #24371 #25956),没有任何 OU 卡。

业务理由:每个打开控制台的用户。权限答复决定导航和按钮能不能画出来,现在它白等一整波(组织列表),租户首页和应用页因此晚一层(round 10:约 0.3 s @290 ms 网络底;staging 更多)。不修,cloud#2914 Target 2「启动关键路径只留 session + me + 当前应用元数据」做不到。

来源

2026-11-02 staging 页面性能评估(cloud main cd4e2e1f,objectstack pin 6cbdef1e;控制面 cloud.objectos.app,租户 os-2ph4c1.objectos.app / HotCRM 6.0.0;内置浏览器面板 zh-CN,读 resource timing 与 v2.7.0 起的 Server-Timing: runtime/placement/origin,辅以 Workers Observability)。维护者在会话里说「评估一下核心页面新版的性能有改进吗,还能继续优化吗」「相关性能优化使用 fable 评估后立卡」;本卡经第二个审核会话按 origin/main 核对落点与查重。
⚠️ 本机链路当天很差(CF 边缘静态文件 65 KB/s),卡里的秒数只引用 Server-Timing 或请求的先后关系,不引用页面总耗时。

已实测

  • 控制面首页瀑布:organization/list 4181→5673 ms,auth/me/permissions 5685 ms 才发出(紧跟其后)→ 7137;之后整层(meta/page、me/localization、me/apps、应用 bundle)在 7144 ms 才发出,等的就是 permissions。
  • 租户客户列表页同样形状:organization/list 1322→1931,auth/me/permissions 1939 发出。
  • 与 round 10(cloud#2914 评论 6396581531)的测量一致;main 与 pin 的挂点相同。

验收

  1. 整页打开的 resource timing 里,auth/me/permissions 的 startTime 与 organization/list 在同一波(差 ≤ 50 ms)。
  2. 请求数不增加、没有重复 URL(cloud verify-console-pin.mjs 的 Target 4 预算读数)。
  3. 请求计数测试 + 消融(挪回原挂点时测试变红)。

相关

cloud#2914(父单,round 10 报告 6396581531 的 OU-3)

🤖 Generated with Claude Code

Activity

  1. added
    bugSomething isn't working
    domain:uiDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p2 (priority added) · 2026-11-02T08:17Z

    ⛔ Not a claim.

    • Read fresh. /auth/me/permissions waits for organization/list because ConsolePermissionsScope is mounted under RequireOrganization, though the active organization is already in the get-session answer. Every Console open pays one extra round trip on the critical path (cloud#2914 OU-3). A user-visible performance defect with named mount points: p2. Routing and the pm state the filer set are unchanged.

    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Claim: PM loop round 2 · 2026-11-02T08:45Z
    Session: session_01QsR2jS5xnxYaE4MkTEF5ko (card thread, os-dev); dispatched by seat session session_01QsR2jRFuJz9QBZqPVHYVhJ
    Account: zhuangjianguo
    Branch: claude/project-thread-y1aiyw (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-29114
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: ui/apps/console/src/AppContent.tsx (the ConsolePermissionsScope mount only), ui/packages/app-shell/src/console/ConsoleShell.tsx (the RequireOrganization boundary only), ui/packages/permissions/src/MePermissionsProvider.tsx, their tests, and a root .changeset; not main.tsx, App.tsx, index.html or lib/auth-preflight.ts (stop on breach; explain in the report)
    Container & model: S/M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: /auth/me/permissions waits for organization/list because ConsolePermissionsScope mounts under RequireOrganization, though the session already names the active organization | the Console start-up path; nav and buttons wait one wave | every user who opens the Console
    Thread-read: none
    Premise: holds (at origin/main, AppContent.tsx mounts ConsolePermissionsScope inside RequireOrganization from ConsoleShell.tsx)
    Serial constraints cleared: PR #29140 (#29039) touches App.tsx and main.tsx, not AppContent.tsx; #29118 (domain:ui#3) holds main.tsx, index.html and auth-preflight.ts, disjoint; merge main before pr_create

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Claim amended · 2026-11-02T08:48Z · on the os-dev's reading before any code. This adds to claim 6572873226 on this card; branch, session, size, Clause-② and Metadata-protocol are unchanged.

  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Claim amended · 2026-11-02T09:22Z · on the os-dev's live run record (app-crm, resource timing). This replaces the App.tsx line of amendment 6572920046; branch, session, size and Metadata-protocol are unchanged.

    • Measured: flipping requireOrganization moved /auth/me/permissions only to the end of the organization/list wave, because every child of ProtectedRoute waits on ConnectedShell's /discovery round trip, which leaves in the same wave. The prop flip is reverted; ProtectedRoute and RequireOrganization stay exactly as on main.
    • Design: MePermissionsProvider gains a take-once held request (the pattern of AuthProvider's boot get-active-member): started for user + org when the session lands, taken once by the first provider with that endpoint and key, dropped otherwise; not a cache. Request count unchanged; a stale session org the list rejects costs one unread request before the redirect.
    • File surface (reworded): ui/apps/console/src/App.tsx, the /home + /apps layout route element only: one sibling element <ConsolePermissionsRequest /> (defined in ui/apps/console/src/AppContent.tsx). MePermissionsProvider.tsx and their tests as before. Serial on App.tsx behind PR feat(mobile): native shell mode — useNativeHost, typed bridge calls, and the Console wired to the mobile shell #29140 unchanged.
    • Clause-②: stays no unless the build shows a new export or prop on published @object-ui/permissions; the os-dev confirms on the built .d.ts and tells the seat before pr_create.
  7. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Claim amended · 2026-11-02T09:40Z · on the os-dev's built .d.ts, before pr_create. This replaces the Clause-② line of amendment 6573543242 on this card; branch, session, size, file surface, serial constraint behind PR #29140 and Metadata-protocol are unchanged.

    Clause-②: yes (widening)
    Metadata-protocol: none

    • Measured (os-dev, @object-ui/permissions built on the card branch; public package, files: [dist]): dist/index.d.ts gains the exports startMePermissionsRequest, releaseMePermissionsRequest and type StartMePermissionsRequestOptions, and MePermissionsProviderProps gains the optional prop requestKey?: string. New exports plus a new optional prop widen the published accept set; nothing is removed or narrowed.
    • Review owed: a widening owes the seat's TIER_DEFAULT contract review (## Contract review record on the PR head), not the contract-review tier. The changeset and PR body carry Clause-②: yes (widening) on their declaration lines.
  8. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jS5xnxYaE4MkTEF5ko
    os-dev-report

    {
      "issue": 29114,
      "status": "done",
      "branch": "claude/project-thread-y1aiyw",
      "pr": 29302,
      "head": "d783ff158a655c4582fb5576f6e558b29442722f",
      "declarations": { "clause_2": "yes (widening)", "metadata_protocol": "none", "source": "claim amendment 6573912180" },
      "files_changed": [
        ".changeset/29114-permissions-organization-list-wave.md (+14)",
        "ui/apps/console/src/App.tsx (+13/-7, layout route element only)",
        "ui/apps/console/src/AppContent.tsx (+59/-4)",
        "ui/apps/console/src/__tests__/App.permissionsWave-29114.test.tsx (+268, new)",
        "ui/packages/permissions/src/MePermissionsProvider.tsx (+141/-5)",
        "ui/packages/permissions/src/__tests__/MePermissionsProvider.heldRequest-29114.test.tsx (+188, new)",
        "ui/packages/permissions/src/index.ts (+3)",
        "ui/apps/console/src/__tests__/App.agentChatLink-10640.test.tsx (+2)",
        "ui/apps/console/src/__tests__/App.docsPortalLazy.test.tsx (+2)",
        "ui/apps/console/src/__tests__/App.nativeShellMode-29039.test.tsx (+2)",
        "ui/apps/console/src/__tests__/i18nAfterSignIn-12034.test.tsx (+2)",
        "ui/apps/console/src/__tests__/internalFormShell.test.tsx (+2)"
      ],
      "line_budget": { "changed": 712, "insertions": 696, "deletions": 16, "files": 12, "human_merge_threshold": 3000, "verdict": "under" },
      "new_public_surface": [
        { "name": "startMePermissionsRequest({ endpoint, fetcher, key })", "why_public": "the caller is the Console route, which mounts before the provider and alone sees the session answer; nothing inside the package can start the request early" },
        { "name": "releaseMePermissionsRequest(endpoint, key)", "why_public": "the caller that started a request must be able to end it when the route is left or the organization changes, else an untaken request stays held and could be read as a stale answer" },
        { "name": "type StartMePermissionsRequestOptions", "why_public": "the options type of startMePermissionsRequest; a public function's parameter type" },
        { "name": "MePermissionsProviderProps.requestKey?: string", "why_public": "the provider is the package's public component and the key is the only way a caller says which question a held answer is for; optional, absent = old behaviour" },
        { "name": "ConsolePermissionsRequest (console app export, not a package)", "why_public": "App.tsx imports it from AppContent.tsx to render it beside ProtectedRoute; the console is not published API" }
      ],
      "acceptance": {
        "prod_build_perm_start_minus_org_list_start_ms": { "origin_main_87d6baef": [87, 66, 58], "branch": [-8, -11, -12] },
        "api_requests": { "origin_main": [20, 19, 19], "branch": [20, 19, 19] },
        "duplicate_urls": { "origin_main": 0, "branch": 0 },
        "dev_server_ms": { "origin_main": [147, 295, 200], "branch": [-17, -22, -25], "note": "main asks twice per open under StrictMode, branch once" },
        "harness": "examples/app-crm, objectstack dev --seed-admin --fresh, Chromium resource timing, 3 opens of /home per leg"
      },
      "tests": {
        "new": { "App.permissionsWave-29114": 4, "MePermissionsProvider.heldRequest-29114": 9 },
        "ablations": [
          { "mutation": "<ConsolePermissionsRequest /> removed from the layout route", "red": 2, "restored": "byte-identical" },
          { "mutation": "provider ignores the held request (const held = null)", "red": 5, "restored": "byte-identical" }
        ],
        "full_console_and_permissions_suite_at_e37c383b": "297 files, 2908 tests green",
        "touched_suites_at_head": "58 files, 482 tests green",
        "ui_scripts_vitest": "169 files green"
      },
      "gates": {
        "derived": 34, "ran": 34, "exit_0": 34, "not_measured": 0, "unrun": 0,
        "sweep_head": "e37c383b (same 12 paths as head; head adds only a clean merge of main)",
        "reconcile": "dispatch-gates --ran: 34 derived, 34 run, 0 NOT-MEASURED",
        "extra": { "check-sdui-manifest": 0, "console type-check": 0, "permissions type-check": 0, "check:spec-symbols": 0, "eslint touched files": "0 errors, 4 warnings", "pnpm build": "117/117", "pr body gates": "changeset-no-major 0, adr-0087 0, closing-keyword-parity 0, partof-closing-keyword 0" }
      },
      "deviations": [
        "Five existing console tests that mock ../AppContent (App.agentChatLink-10640, App.docsPortalLazy, App.nativeShellMode-29039, i18nAfterSignIn-12034, internalFormShell) got one stub line each (ConsolePermissionsRequest: () => null) without asking first; vitest refuses a missing mock export. Outside the claim's named files unless 'their tests' covers App.tsx's route-table tests; asking for an after-the-fact amendment.",
        "ui/packages/permissions/src/index.ts (3 export lines) is outside the named file list; the exports are the ones amendment 6573912180 declares.",
        "First design (requireOrganization={false} prop flip) measured insufficient (+51/+66/+60 ms, waits on /discovery) and reverted; replaced by the held request per amendment 6573543242.",
        "Code was written before the run record.",
        "eslint react-refresh/only-export-components: 2 new warnings on MePermissionsProvider.tsx (non-component exports); warnings only.",
        "Measured on local app-crm, not cloud."
      ],
      "known_cost": "a stale session whose active organization the list does not confirm sends one unread permissions request, then redirects to /organizations as before",
      "writes": { "pr_create_relay": 1, "post_stamped": 1, "git_pushes": "branch only" },
      "mcp_calls": { "github_reads": "issue_read x3, pull_request_read x2", "github_writes": 0, "subscribe_pr_activity": 1 }
    }

    Generated by Claude Code

  9. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Claim amended (after the fact) · 2026-11-02T11:27Z · on the os-dev's report 6575961170, PR #29302 head d783ff15. This adds five files to the surface of amendment 6573543242; branch, session, size, Clause-② (6573912180) and Metadata-protocol are unchanged.

    • Measured: App.tsx now imports ConsolePermissionsRequest from ./AppContent, and five existing console tests mock ../AppContent with a factory that lacks that export, so vitest refused them. The full-suite run caught it before pr_create.
    • File surface (added): one stub line ConsolePermissionsRequest: () => null (plus its comment line) in each of ui/apps/console/src/__tests__/App.agentChatLink-10640.test.tsx, App.docsPortalLazy.test.tsx, App.nativeShellMode-29039.test.tsx, i18nAfterSignIn-12034.test.tsx and internalFormShell.test.tsx. Mechanical, forced by the declared App.tsx line; no assertion changes. ui/packages/permissions/src/index.ts (the three export lines) was already covered by the Clause-② amendment.
    • Process note: the stubs were written before this amendment; the seat accepts them because they carry no behaviour and the alternative (a test that cannot load) is not a choice. The report names them, which is the order the rule asks for when a stop would have cost a round with nothing to decide.
  10. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Landed · 2026-11-02T12:28Z · PR #29302 merged through the queue as 5901871c; the merge commit carries all 12 files of the accepted head d783ff15 (the held request and requestKey in MePermissionsProvider, ConsolePermissionsRequest in the Console route, the five test-mock stubs, the tests, the changeset). Delivered in full: nothing remains on this card; pm:dispatched removed.

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

Metadata

Metadata

Assignees

Labels

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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions