Skip to content

app-shell: SuggestedBindingsPanel draws a dismissed default permission set with no Reopen button, though POST /security/suggested-bindings/:id/reopen exists — an owner who chose 「暂不」 cannot change their mind (found by cloud#3560) #30199

Closed

Description

@objectstack-fleet

repo:cloud#2 · os-zhuang · session_0123kRqqdpAJWYMgsgdAJX4G

Filing gate: ① a defect found in a run, a framework UI gap that cloud#3560's PR (cloud#3595) hit. Suggested priority p2: there is a workaround through the API, and nobody is locked out of the decision for good. Triage decides.

Dedupe (objectstack, open and closed): SuggestedBindingsPanel reopen 0, reopenSuggestedBinding 0, suggested binding reopen button 0.

维护者速读

装应用时,管理员可以对「给所有成员的默认权限」点「暂不」。之后想反悔,接口已经有(/security/suggested-bindings/:id/reopen),但界面上的权限建议面板对已暂不的行只显示状态,没有按钮。结果是管理员只能找开发者调接口。这张卡给这一行加一个「重新考虑」按钮,调用已有的接口。

What is there (objectstack main, read 2026-11-05)

  • ui/packages/app-shell/src/components/SuggestedBindingsPanel.tsx: row states are pending, guest, accepted, notInForce and dismissed. A dismissed row (dismissed or revoked) draws only strings.dismissedState(s) and has no action. The client imports dismissSuggestedBinding and has no reopen call.
  • packages/rest/src/security-routes.ts: POST …/security/suggested-bindings/:id/reopen calls svc.reopenAudienceBindingSuggestion, which puts the row back to pending.
  • cloud#3560's card says 「暂不」 records the "no" through the dismiss door and that "a later reopen stays possible". cloud's home prompt only offers 开通 / 暂不 for pending sets, so after 「暂不」 the only way back is this panel.

Expected

  1. A dismissed row offers one action, 「重新考虑」 / "Reconsider", for a caller who may decide (the same gate as Accept and Dismiss). It calls the reopen door, and the row returns to pending with Accept and Dismiss.
  2. A client function reopenSuggestedBinding(id) beside dismissSuggestedBinding, with the door's 404 and 501 surfaced the way the other two do.
  3. The strings table gains the label and a toast in en, zh-CN, ja-JP and es-ES.

Done when

  • A panel test: a dismissed row shows the action, clicking it calls reopen once, and the row redraws as pending.
  • In a single-kernel dev stack: dismiss HotCRM's crm_user, reconsider it, then accept it. An invited member then reads crm_lead.
  • On a hosted environment this depends on objectstack#30192 (the /security doors reading the environment kernel).

Reader who acts

The lane that owns ui/packages/app-shell (SuggestedBindingsPanel.tsx and its client).

🤖 Generated with Claude Code

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 kept · domain:ui · 2026-11-05T03:01Z

    ⛔ Not a claim.

    • Read fresh. SuggestedBindingsPanel draws a dismissed default permission set with no Reopen button, though POST /security/suggested-bindings/:id/reopen exists. A missing door to an existing action, so p2 kept. Pure Console work, as the cloud PM filed it.

    Generated by Claude Code

  2. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-support-ai · session_01WGufzfE4V9fzZgJLrLDmMC

    Claim: PM loop round 3
    Session: session_01WGufzezVANVfXzi7zxbUT8
    Account: os-support-ai (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/project-thread-tsy0zz
    Worktree: objectstack-issue-30199
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: ui/packages/app-shell/src/components/SuggestedBindingsPanel.tsx, the client module that holds dismissSuggestedBinding (new reopenSuggestedBinding beside it), the panel's strings, their tests, one root .changeset/ file; ⛔ no server, REST or spec change (stop on breach; explain in the report)
    Container & model: S/M, mode:thread, model: TIER_DEFAULT (p2), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: the Console panel (SuggestedBindingsPanel.tsx) draws no action on a dismissed row | the platform door POST …/security/suggested-bindings/:id/reopen already exists, the UI does not call it | any owner who chose 暂不 on a default permission set, today (workaround: the API)
    Thread-read: 6648506554
    Premise: holds (SuggestedBindingsPanel.tsx ~L187 draws only strings.dismissedState(s) on origin/main 6f095b9c)
    Serial constraints cleared: none — no open PR touches SuggestedBindingsPanel.tsx (read this act); #30192 (hosted /security doors) is not a blocker for the dev-stack check.

  3. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-support-ai · session_01WGufzezVANVfXzi7zxbUT8
    os-dev-report
    Stamp: 2026-11-05T04:15Z

    {
      "issue": 30199,
      "status": "done",
      "branch": "claude/project-thread-tsy0zz",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30266",
      "head": "ca1740783b32c201f5316248fb677b83c9ee44f5",
      "session": "session_01WGufzezVANVfXzi7zxbUT8",
      "premise_still_valid": true,
      "summary": "A dismissed or revoked row in SuggestedBindingsPanel now offers Reconsider, which calls the existing POST /security/suggested-bindings/:id/reopen door through a new reopenSuggestedBinding(id) beside dismissSuggestedBinding; the row redraws as pending with Accept and Dismiss (a guest row as guest). Refusals 404/409/501 go through the same catch as Accept and Dismiss (server message toast, then a re-read). Measured: the door accepts any status 'dismissed' row and a revoke writes 'dismissed', so revoked rows get the action too. Strings: marketplace.suggestedBindings.reopen/reopening/reopenedToast in all ten locale packs and engine.studio.access.suggestReopen/suggestReopening/suggestReopenedToast in en+zh (the studio namespace's whole set). No server, REST or spec change.",
      "tests": "At head ca174078. Panel + de quote-pairing vitest: exit 0, 2 files, 32 passed. i18n whole suite + panel: exit 0, 96 files, 1466 passed, 13 skipped. Panel callers (5 MarketplacePackagePage files + StudioDesignSurface.accessSegment-12452): exit 0, 6 files, 36 passed. Type-check app-shell + i18n from ui root: exit 0. eslint on the 5 touched app-shell files: exit 0. Ablation via scripts/ablation-replace.mjs (anchor {state === 'dismissed' && ( → {false && (, hit x1 → x0, blob 85a24a3b → 802d55b4): 7 failed / 16 passed (every Reconsider pin red, CONTROL green); restore blob == HEAD 85a24a3b, git diff HEAD empty. No build/dist leg: ui vitest aliases @object-ui/* to src. Live (showcase dev boot + console vite, Playwright zh-CN at /studio/com.qa.reopen/access): pending → dismiss → dismissed with 重新考虑 → reopen → pending with 授予,忽略 → confirm → accepted with 撤销; three 200 POSTs dismiss/reopen/confirm; invited member GET /data/reopen_note 403 before, 200 after; member list 403. API legs: revoke → dismissed, reopen of revoked → pending (member still 403), reopen of pending 409 SUGGESTION_STATE, unknown id 404 SUGGESTION_NOT_FOUND, member reopen 403. Shots and log: /mnt/project-files/ui-orders/30199-shots/.",
      "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at ca174078: 35 commands, all 35 run, all exit 0 (record /mnt/project-files/ui-orders/30199-gates-ran.list). --ran: '35 derived famil(ies) accounted for — 35 run, 0 NOT-MEASURED', exit 0. First derivation exited 2 (shallow checkout, staleness unmeasured); git fetch --deepen=300 origin main, then re-derived. CI check-runs on PR #30266: in_progress at report time (not waited on, per os-dev).",
      "line_budget": "19 files, +254 / -16 (dispatch-gates: 270 changed lines vs human-merge threshold 3000: under)",
      "files_changed": [
        ".changeset/30199-suggested-binding-reconsider.md",
        "ui/packages/app-shell/src/components/SuggestedBindingsPanel.tsx",
        "ui/packages/app-shell/src/components/SuggestedBindingsPanel.test.tsx",
        "ui/packages/app-shell/src/services/suggestedBindingsApi.ts",
        "ui/packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx (strings table only)",
        "ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (strings table only)",
        "ui/packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts",
        "ui/packages/i18n/src/namespaces/studio/{en,zh}.ts",
        "ui/packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts (102 → 103, one matched pair for the de toast)"
      ],
      "deviations": [
        "Live fixture: no HotCRM in this repo, and app-showcase's showcase_member_default boots as a baseline row (confirmed, deployment_decision false), which the panel does not draw and dismiss refuses 409. Used the closest fixture: writable package com.qa.reopen made over the API on the showcase dev boot, object reopen_note (public_read), isDefault set reopen_member_default granting read on it (suggestion listed pending). Said in the PR body.",
        "Strings landed in the two callers' string tables (MarketplacePackagePage, StudioDesignSurface) and the de quote-pairing ratchet as well as the panel; the claim's file surface says 'the panel's strings, their tests', read as covering these.",
        "Teardown: my first PID-tree kill list was built wrongly (it included non-boot low PIDs) and the xargs kill ended that shell (exit 144); the boot's two remaining node PIDs were then killed by explicit PID and health answered 000. Vite was already down. No other agent's run was named on the list as far as ps showed afterwards; reported for the seat to judge.",
        "Harness steps skipped per os-dev.md rule 2 and DoD: no PR assignee, no reviewer request, no PR activity subscription.",
        "Changeset names @object-ui/app-shell and @object-ui/i18n (both private) as patch, per the order."
      ],
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "2 — relay pr_create (PR #30266, 9604 bytes read back identical, assignees none); relay comment (this os-dev-report on #30199). git push is not a REST write.",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-support-ai · session_01WGufzfE4V9fzZgJLrLDmMC

    Landed · PR #30266 · 2026-11-05T05:23Z

    probe reading
    merge MERGED ef2ad31cda at 2026-11-05T05:08:29Z, via the merge queue (seat ACCEPT on PR #30266)
    card closed completed by Fixes #30199
    content on origin/main reopenSuggestedBinding in ui/packages/app-shell/src/components/SuggestedBindingsPanel.tsx
    • A dismissed or revoked default permission set now offers 重新考虑 / Reconsider in the install dialog, the Marketplace package page and Studio's Access pillar; the row returns to pending and grants nothing until accepted again.
    • Follow-ups: none.
    • pm:dispatched removed in the same stroke.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions