Skip to content

setup: the AI Approvals nav entry is gated by manage_platform_settings, so a builder whose MCP proposal waits there reaches it only by URL (cloud#3685 review) #31029

Open

Description

@objectstack-fleet

repo:cloud#3 · hotlong · session_01Q4EjjRhUZjdy8VXs6Kkur2

Filing gate: (c) should-fix carried from a contract review (objectstack-ai/cloud#3685, review 6692522928). The MCP build door's staged removals are approved by their proposer on the console's AI Approvals page.

维护者速读

通过 MCP 发起的「清理示例数据」要本人在「AI 审批」页面批准,但 Setup 里这个页面的入口只有有平台设置权限的人才看得到。一个只有搭建权限的人,只能靠 MCP 返回的网址才能找到它。需要让能发起待办的人在导航里也看得到自己的审批入口。

Readings

  • Framework platform-objects setup.app.ts: group_approvals is gated by manage_platform_settings.
  • The page itself serves proposer-only actions, so a builder with manage_metadata can open it by URL (/_console/apps/setup/system/ai-approvals).

Expected

  • The nav entry is visible to anyone who can have a pending action, i.e. who can propose one. The lane names the right grant, or splits "my approvals" from the admin view. ⛔ It must not widen what the page lets them approve.

Acceptance

  • A builder without manage_platform_settings sees the entry and only their own proposals; an admin view stays gated.

Suggested-grade: p2.

Activity

  1. added
    enhancementNew feature or request
    pm:queueReady for the PM dispatch loop
    repo:cloudCard routed whole to the cloud PM: needs cloud code, a producer or a fact (cloud owns it to closure)
    domain:cloudTouches cloud: the whole card is the cloud PM's (repo:cloud seat); no objectstack lane claims it
    domain:serverDomain lane — seat card indexed by label:pm:seat
    and removed
    domain:cloudTouches cloud: the whole card is the cloud PM's (repo:cloud seat); no objectstack lane claims it
    on Nov 6, 2026
  2. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p2 kept · domain:cloud → domain:server · 2026-11-06T18:56Z

    ⛔ Not a claim.

    • Setup's AI Approvals nav entry is gated by manage_platform_settings (setup.app.ts, group_approvals), so a builder whose MCP proposal waits there reaches the page only by URL. From cloud#3685's contract review.
    • Lane moved to domain:server. The change is in the framework's platform-objects. Cloud seats' objectstack-code cards go to objectstack lanes, and repo:cloud follows. p2 kept, pm:queue.
    • ⛔ As the card says, showing the entry must not widen what the page lets anyone approve. The admin view stays gated.

    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 7, 2026
  4. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · marchtian · session_017ihL2dFb2QdZEHEJ83cR2B

    Claim: PM loop round 1 · 2026-11-07T12:26Z
    Session: session_017ihL2dFb2QdZEHEJ83cR2B
    Account: marchtian
    Branch: claude/project-thread-4b4c9o
    Worktree: objectstack-issue-31029 (the card thread's own checkout)
    Domain: domain:server
    Seat: domain:server#3
    File surface: packages/platform-objects/** (setup.app.ts and its tests) (stop on breach; explain in the report)
    Container & model: M, mode:thread (card thread cmsg_01VmuUhXU9SSUzqJYyXSmYSi6CEU5Rfyv67ukVUZQPCPHe of this account's project), model: TIER_DEFAULT — dispatch-gates --tier: no path-derived mandate, effort: session default — card-thread effort is set by the maintainer only; the seat's reading is high (M)
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6692895097
    Premise: holds — read at origin/main 5f00374: setup.app.ts group_approvals carries requiredPermissions [manage_platform_settings]
    Serial constraints cleared: no open domain:server claim names setup.app.ts; siblings #31085/#31032 (this seat) touch other platform-objects files

    The dispatch order is the card thread's opening message (files server-seat-3/orders/_standing.md + server-seat-3/orders/31029.md in this account's project); slot granted by the project coordinator.

  5. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · marchtian · session_017ihL2eWvnitALhePppsWuB

    os-dev-report

    {
      "issue": 31029,
      "status": "needs_decision",
      "branch": "claude/project-thread-4b4c9o",
      "pr": null,
      "session": "session_017ihL2eWvnitALhePppsWuB",
      "premise_still_valid": false,
      "summary": "Readings at origin/main 5f003744; no code written, per the seat's instruction. The AI Approvals nav entry (componentRef ai:approvals) is not in objectstack: zero hits outside ui/, and platform-objects changeset fa0a4b6 records that the entry is the AI capability's (service-ai, Cloud/Enterprise) to contribute under ADR-0029 D7. Cloud's contribution lands in Setup group_approvals and inherits its manage_platform_settings gate. requiredPermissions is all-of (holdsRequiredPermissions in packages/rest/src/meta-item-read-gate.ts, ruling 6095014058) and a group that fails its gate drops with all its children. group_approvals also holds plugin-approvals' Approvals Inbox plus the Requests / Action History / Delegations tables, whose contribution comment relies on the group gate, so widening the group (option a in the order) exposes them. The Setup app requires setup.access, which a manage_metadata-only builder may not hold. proposePendingAction, listPendingActions and /api/v1/ai/pending-actions are implemented in cloud service-ai; the console page lists whatever that route returns (no proposer filter in usePendingActions / AiPendingActionsInbox), so 'only their own proposals' can be neither delivered nor measured in this repo.",
      "tests": "none run: reading only",
      "gates": "none run: no diff",
      "dogfood_battery": "n/a",
      "mcp_calls": "0",
      "api_writes": "1 — this os-dev-report comment, POST issues/31029/comments via post-stamped.mjs",
      "open_questions": [
        {
          "question": "Where does a proposer-visible AI Approvals entry live, and who scopes the list to own proposals?",
          "options": [
            "A: cloud only. service-ai contributes a second, proposer-facing entry (Studio group_ai or the account app) gated requiredPermissions [manage_metadata] plus its own requiresService, and its list route returns only proposed_by = caller to a non-admin. The Setup entry stays admin-only. objectstack diff: none; card returns to repo:cloud.",
            "B: platform-objects adds nav_ai_approvals (componentRef ai:approvals) to Studio group_ai, requiredPermissions [manage_metadata], requiresService ai. About 15 lines plus a test. Reverses the recorded fa0a4b6 stance; the service name and own-proposals-only scoping are cloud facts this repo cannot verify, so it can advertise the whole queue to builders if cloud does not scope.",
            "C: setup.app.ts gains a new slot group_my_approvals gated [manage_metadata], cloud retargets its contribution. Two repos; still needs setup.access, which a plain manage_metadata builder may lack; the slot collapses empty until cloud lands."
          ],
          "recommendation": "A, because the entry, the proposer, the store and /api/v1/ai/pending-actions all live in cloud service-ai, so only cloud can make Acceptance's 'only their own proposals' true; A widens nothing here."
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": []
    }
  6. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · marchtian · session_017ihL2dFb2QdZEHEJ83cR2B

    Release: session_017ihL2dFb2QdZEHEJ83cR2B · premise falsified (dev report 6706974497) · back to pm:queue + pm:retriage, unassigned · 2026-11-07T12:32Z

    Nothing was built: no commit, no push, no PR (branch claude/project-thread-4b4c9o untouched). The claim 6706930388 is withdrawn.

    Why the premise fails (the dev's readings at origin/main 5f0037449, spot-checked by the seat):

    • The AI Approvals nav entry (componentRef: ai:approvals) is not contributed by objectstack. The platform-objects changeset fa0a4b6 records it as the AI capability's own contribution (cloud service-ai, ADR-0029 D7); cloud places it in Setup group_approvals, so it inherits manage_platform_settings.
    • requiredPermissions is all-of, and a gated group drops with all its children. group_approvals also holds plugin-approvals' Inbox, Requests, Action History and Delegations, whose comment relies on the group gate, so loosening the group would expose them.
    • proposePendingAction, listPendingActions and /api/v1/ai/pending-actions are cloud. The page shows whatever that API returns, with no proposer filter, so the Acceptance line "sees … only their own proposals" cannot be delivered or measured in this repo.

    Question to triage (routing, not a product decision): the dev's option A, which the seat also reads as the fit, puts the whole change in cloud: service-ai adds a proposer-facing entry (Studio group_ai or the account app) gated on manage_metadata with its own requiresService, and its list route scopes non-admins to proposed_by = caller. The objectstack diff is none, so this card belongs to repo:cloud. Options B (a platform-objects Studio entry, reversing fa0a4b6) and C (a new Setup slot plus a cloud retarget) are in the report; if triage reads either as wanted, that is a maintainer decision card, not a routing call.

  7. added
    pm:queueReady for the PM dispatch loop
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    and removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Nov 7, 2026
  8. added
    domain:cloudTouches cloud: the whole card is the cloud PM's (repo:cloud seat); no objectstack lane claims it
    and removed
    domain:serverDomain lane — seat card indexed by label:pm:seat
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    on Nov 7, 2026
  9. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: re-route · domain:server → domain:cloud · 2026-11-07T12:36Z

    ⛔ Not a claim.

    • Correction. Triage's R943 audit moved this card to domain:server, reading the fix as framework platform-objects because group_approvals lives in setup.app.ts. That premise was false. domain:server#3's dev (6706974497, release 6706985350) shows that the AI Approvals entry (componentRef: ai:approvals) is contributed by cloud service-ai (ADR-0029 D7, changeset fa0a4b6). The pending-actions API and its proposer scoping are cloud's too. Loosening group_approvals would also expose plugin-approvals' entries.
    • Route: option A, which puts the whole change in cloud. service-ai adds a proposer-facing entry gated on manage_metadata, and its list route scopes non-admins to their own proposals. The objectstack diff is none, so the card goes back to the cloud lane (「一个issue只要涉及 cloud ,就归 cloud pm 处理」): domain:cloud, repo:cloud kept, pm:queue, pm:retriage removed. p2 kept.
    • Options B and C (a platform-objects entry, reversing fa0a4b6, or a new Setup slot) would be product decisions. Triage does not choose them. If the cloud seat finds A insufficient, it goes on a decision card.

    Generated by Claude Code

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

    domain:cloudTouches cloud: the whole card is the cloud PM's (repo:cloud seat); no objectstack lane claims itenhancementNew feature or requestpm:queueReady for the PM dispatch looppriority:p2Medium: important, M3repo:cloudCard routed whole to the cloud PM: needs cloud code, a producer or a fact (cloud owns it to closure)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions