You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
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
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.
Framework platform-objectssetup.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.
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.
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.
{
"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": []
}
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.
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.
Activity
objectstack-fleet commentedon Nov 6, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: audit · p2 kept ·
domain:cloud→domain:server· 2026-11-06T18:56Z⛔ Not a claim.
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.domain:server. The change is in the framework'splatform-objects. Cloud seats' objectstack-code cards go to objectstack lanes, andrepo:cloudfollows. p2 kept,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Nov 7, 2026
domain:server#3 · marchtian · session_017ihL2dFb2QdZEHEJ83cR2B
Claim: PM loop round 1 · 2026-11-07T12:26Z
Session:
session_017ihL2dFb2QdZEHEJ83cR2BAccount:
marchtianBranch:
claude/project-thread-4b4c9oWorktree:
objectstack-issue-31029(the card thread's own checkout)Domain:
domain:serverSeat:
domain:server#3File 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:serverclaim names setup.app.ts; siblings #31085/#31032 (this seat) touch other platform-objects filesThe dispatch order is the card thread's opening message (files
server-seat-3/orders/_standing.md+server-seat-3/orders/31029.mdin this account's project); slot granted by the project coordinator.objectstack-fleet commentedon Nov 7, 2026
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": [] }objectstack-fleet commentedon Nov 7, 2026
domain:server#3 · marchtian · session_017ihL2dFb2QdZEHEJ83cR2B
Release:
session_017ihL2dFb2QdZEHEJ83cR2B· premise falsified (dev report 6706974497) · back topm:queue+pm:retriage, unassigned · 2026-11-07T12:32ZNothing was built: no commit, no push, no PR (branch
claude/project-thread-4b4c9ountouched). The claim 6706930388 is withdrawn.Why the premise fails (the dev's readings at origin/main
5f0037449, spot-checked by the seat):componentRef: ai:approvals) is not contributed by objectstack. The platform-objects changesetfa0a4b6records it as the AI capability's own contribution (cloudservice-ai, ADR-0029 D7); cloud places it in Setupgroup_approvals, so it inheritsmanage_platform_settings.requiredPermissionsis all-of, and a gated group drops with all its children.group_approvalsalso holds plugin-approvals' Inbox, Requests, Action History and Delegations, whose comment relies on the group gate, so loosening the group would expose them.proposePendingAction,listPendingActionsand/api/v1/ai/pending-actionsare 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-aiadds a proposer-facing entry (Studiogroup_aior the account app) gated onmanage_metadatawith its ownrequiresService, and its list route scopes non-admins toproposed_by= caller. The objectstack diff is none, so this card belongs torepo:cloud. Options B (a platform-objects Studio entry, reversingfa0a4b6) 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.objectstack-fleet commentedon Nov 7, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: re-route ·
domain:server→domain:cloud· 2026-11-07T12:36Z⛔ Not a claim.
domain:server, reading the fix as frameworkplatform-objectsbecausegroup_approvalslives insetup.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 cloudservice-ai(ADR-0029 D7, changesetfa0a4b6). The pending-actions API and its proposer scoping are cloud's too. Looseninggroup_approvalswould also expose plugin-approvals' entries.service-aiadds a proposer-facing entry gated onmanage_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:cloudkept,pm:queue,pm:retriageremoved. p2 kept.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