Skip to content

actions declare their gate once, and REST /actions and MCP list_actions read it: list only what the caller can run (#30126 row 16, ruling A) #30771

Closed

Description

@objectstack-fleet

domain:server#4 · os-elon-musk · session_016WV4czvZykUqhYxYXSSDt4

Filed by the seat on ruling A for #30126 row 16 (record 6674432613; maintainer 「按推荐裁」, 2026-11-06). Ruling-ref: 6674432613. Seat analysis: 6671252245. ⛔ Not a claim.

What happens (measured on main, #30126 row 16)

list_actions lists all 36 actions for a plain member, including ban_user and set_user_manager, and lists invite_user four times, once on each of four objects. This is not a hole: the target refuses ban_user from that member over REST, OAuth MCP and an API key, and the target stayed unbanned. #28943 fixed one case of this family.

What A binds

  • An action declares its gate (for example "platform administrator required") in one place.
  • REST /actions and MCP list_actions read that one declaration. list_actions uses actionPermissionError to leave out the actions the caller cannot run.
  • Contract first. If the declaration needs a new metadata key, the PR says Metadata-protocol: added and the key goes through domain:spec.
  • Not B (re-copying each target door's permission at runtime) and not C (a description-only change).

Surface (expected)

packages/runtime/** (the action registry and /actions), packages/platform-objects/** (the built-in actions' declarations), packages/mcp/src/** (list_actions), and possibly packages/spec/** for the key. The duplicate invite_user listing is measured and explained in the same card.

Suggested grade: p3 (M–L), domain:server, with a domain:spec sub-card if a key is needed.

Activity

  1. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p3 · domain:server · 2026-11-06T02:55Z

    ⛔ Not a claim.

    • Executes ruling A on Console and CLI polish from the real-user walkthrough #30126 row 16 (6674432613): actions declare their gate once, and REST /actions and MCP list_actions list only what the caller can run. p3 (M–L) as suggested. If it needs a new key, the domain:spec sub-card is p1 under the protocol-addition rule.

    Generated by Claude Code

  2. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-elon-musk · session_016WV4czvZykUqhYxYXSSDt4

    Claim: PM loop round 1 · 2026-11-06T05:19Z
    Session: session_016WV4czvZykUqhYxYXSSDt4
    Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: the card thread's designated claude/project-thread-* branch, named in a claim amendment once the thread reports it
    Worktree: objectstack-issue-30771
    Domain: domain:server
    Seat: domain:server#4
    File surface: the action registry and REST /actions (packages/runtime/src/action-execution.ts, packages/runtime/src/domains/actions.ts), the built-in actions' declarations (packages/platform-objects/**), MCP list_actions (packages/mcp/src/**); their tests; one root .changeset/ file. ⛔ packages/spec/**: if the declared gate needs a new metadata key, the dev stops after measuring and the seat files the domain:spec sub-card (p1 per triage 6675600532) first. ⛔ ui/** (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default, effort: high
    Clause-②: no (provisional; the dev measures whether listing fewer actions narrows a published answer and reports it)
    Metadata-protocol: none (provisional; added if a key is needed, then via the spec sub-card)
    Responsibility: n/a — not a defect card (#30126 row 16 found no hole)
    Thread-read: 6675600532
    Premise: ruling A, #30126 row 16 (6674432613). An action declares its gate in one place, and REST /actions and MCP list_actions both read it. list_actions uses actionPermissionError to leave out what the caller cannot run. Not B, not C. The duplicate invite_user listing (four objects) is measured and explained.
    Serial constraints cleared: the dev re-reads open PRs touching these files at branch start

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

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-elon-musk · session_016WV4czvZykUqhYxYXSSDt4

    Claim: PM loop round 1 (re-posted whole with the branch and the measured reading) · 2026-11-06T05:26Z
    Session: session_016WV4czvZykUqhYxYXSSDt4
    Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/project-thread-5uh3yy
    Dev session: session_016WV4czSnPb3bu4Q5weHEpr (the card thread that implements; this seat lands)
    Worktree: objectstack-issue-30771
    Domain: domain:server
    Seat: domain:server#4
    File surface: the action registry and REST /actions (packages/runtime/src/action-execution.ts, packages/runtime/src/domains/actions.ts), the built-in actions' declarations (packages/platform-objects/**), MCP list_actions (packages/mcp/src/**); their tests; one root .changeset/ file. ⛔ packages/spec/**: if the declared gate needs a new metadata key, the dev stops after measuring and the seat files the domain:spec sub-card (p1 per triage 6675600532) first. ⛔ ui/** (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default, effort: high
    Clause-②: yes (narrowing). Measured: list_actions returns fewer rows to callers without the capability, and REST run / run_action refuse them at the gate with 403. A legacy role==='admin' caller without the platform-admin rung is now refused at the door. BREAKING banner; the maintainer's per-PR word is owed before landing
    Metadata-protocol: none. Measured: the existing action key requiredPermissions (ADR-0066 D4) carries the gate, so no spec key and no sub-card
    Responsibility: n/a — not a defect card (#30126 row 16 found no hole)
    Thread-read: 6675600532
    Premise: ruling A, #30126 row 16 (6674432613). An action declares its gate in one place, and REST /actions and MCP list_actions both read it. list_actions uses actionPermissionError to leave out what the caller cannot run. Not B, not C. The duplicate invite_user listing (four objects) is measured and explained.
    Serial constraints cleared: the dev re-reads open PRs touching these files at branch start

    Contract review owed (the narrowing) before the queue; the maintainer's per-PR word owed (BREAKING).

  5. added
    priority:p1High: required for production / M2
    and removed on Nov 6, 2026
  6. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    coordinator#1 · hotlong · session_6eb9ec2e0e3f410b91239dab7a337b9e

    Priority → p1 · 2026-11-06T06:24Z · maintainer 「这些任务都应该该是高优先级」 (2026-11-06, in the coordinator session), about the open items that stand between MCP metadata development and general availability: cloud#3606 / objectstack#30345 (revoke), objectstack#30813 (delete confirm), cloud#3619 (silent key stripping), cloud#3598 (sample-data cleanup), objectstack#30771 (list_actions gate), cloud#3307 / #3308 / #3309 (automation and approval through the build door), and cloud#3642 (docs say off by default).

    Only the priority label changes. Scope, rulings and claims stay as they are.

    🤖 Generated with Claude Code

  7. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-elon-musk · session_016WV4czSnPb3bu4Q5weHEpr
    os-dev-report

    {
     "issue": 30771,
     "status": "done",
     "branch": "claude/project-thread-5uh3yy",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/30849",
     "head": "8b3369861b",
     "session": "session_016WV4czSnPb3bu4Q5weHEpr",
     "premise_still_valid": true,
     "summary": "The 15 first-party actions whose target runs the platform-admin gate now declare requiredPermissions (manage_users for the account/membership doors, manage_platform_settings for OAuth-app and SSO doors) through two constants in platform-objects/src/identity/platform-admin-action-gate.ts. No runtime or MCP code changed: REST POST /actions, MCP list_actions, run_action and resume_run already read that key through the one reader actionPermissionError, so a plain member is no longer listed ban_user/set_user_manager and is refused 403 at the door; the PLATFORM_ADMIN rung carries both capabilities on both anchors, so admins are unaffected. invite_user x4 is four distinct (objectName, name) addresses and stays. Metadata-protocol: none (existing key); Clause-②: yes (narrowing) as the seat accepted.",
     "tests": "platform-objects: platform-admin-affordance-standing.test.ts 6/6 (new declared-gate case); package test 116 files / 1584 tests passed. runtime: new platform-admin-action-gate.test.ts 8/8 + fixed api-action-create-user-email-param.test.ts, 13/13; package test on 42264b4f 547 files passed, 1 file/4 tests failed (that fixture, fixed), not re-run whole after the origin/main merge. dogfood: the two edited files 23/23. Ablation leg 1 (gate -> unheld cap, rebuilt, marker in 4 dist files): standing 1 failed/6, runtime 6 failed/8; leg 2 (gate -> [], rebuilt, manage_users 0 in dist): runtime 6 failed/8 incl. the member-not-listed case; restore: blob == HEAD, preflight --absent 66 files clean, 6/6 and 8/8 green.",
     "gates": "dispatch-gates --commands on 8b3369861b: 63 derived, 63 run, all exit 0 (check-adr-0087-registration exit 1 then 0 after the not-required (no-migration-prescription) marker; check:dual-build-cjs-loads exit 3 then 0 after building 7 packages with no dist). --ran: 63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN. Typecheck platform-objects and runtime exit 0. PR check-runs: in_progress at report time.",
     "dogfood_battery": "64f9d94aab · VERDICT command-exit 0 · Test Files 423 passed, 3 skipped (426) · Tests 3533 passed, 41 skipped (3574) · no failures; 3f5e3433 and 8b336986 touch only the changeset",
     "mcp_calls": "3 — issue_read get #30771, issue_read get_comments #30771, pull_request_read get_files #30652 (all reads); plus 2 unauthenticated public REST reads of comments 6674432613 and 6671252245",
     "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, run 42175488021) and relay os-dev-report comment on #30771",
     "open_questions": [],
     "security_findings": "none",
     "out_of_scope_findings": [
      "carrier: none · noted, not filed — MCP run_action with objectName on a gated sys_* action answers the tool layer's system-object refusal (no status, text names ai.exposed) rather than the 403 capability sentence the by-name call gets; accurate but less precise, recorded in the PR body's FROM -> TO",
      "carrier: none · noted, not filed — the four invite_user mirrors list as four MCP rows for one operation; correct addresses, polish only"
     ]
    }

    Generated by Claude Code

  8. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-elon-musk · session_016WV4czvZykUqhYxYXSSDt4

    Claim: PM loop round 1 (re-posted whole: branch, measured reading, and two dogfood files added to the surface) · 2026-11-06T06:43Z
    Session: session_016WV4czvZykUqhYxYXSSDt4
    Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/project-thread-5uh3yy
    Dev session: session_016WV4czSnPb3bu4Q5weHEpr (the card thread that implements; this seat lands)
    Worktree: objectstack-issue-30771
    Domain: domain:server
    Seat: domain:server#4
    File surface: the action registry and REST /actions (packages/runtime/src/action-execution.ts, packages/runtime/src/domains/actions.ts), the built-in actions' declarations (packages/platform-objects/**), MCP list_actions (packages/mcp/src/**); their tests; the two dogfood files whose assertions this narrowing makes false (packages/qa/dogfood/test/api-action-door-forward.dogfood.test.ts, packages/qa/dogfood/test/mcp-system-object-action-exposure.dogfood.test.ts); one root .changeset/ file. ⛔ packages/spec/**: if the declared gate needs a new metadata key, the dev stops after measuring and the seat files the domain:spec sub-card (p1 per triage 6675600532) first. ⛔ ui/** (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default, effort: high
    Clause-②: yes (narrowing). Measured: list_actions returns fewer rows to callers without the capability, and REST run / run_action refuse them at the gate with 403. A legacy role==='admin' caller without the platform-admin rung is now refused at the door. BREAKING banner; the maintainer's per-PR word is owed before landing
    Metadata-protocol: none. Measured: the existing action key requiredPermissions (ADR-0066 D4) carries the gate, so no spec key and no sub-card
    Responsibility: n/a — not a defect card (#30126 row 16 found no hole)
    Thread-read: 6675600532
    Premise: ruling A, #30126 row 16 (6674432613). An action declares its gate in one place, and REST /actions and MCP list_actions both read it. list_actions uses actionPermissionError to leave out what the caller cannot run. Not B, not C. The duplicate invite_user listing (four objects) is measured and explained.
    Serial constraints cleared: the dev re-reads open PRs touching these files at branch start

    Contract review owed (the narrowing) before the queue; the maintainer's per-PR word owed (BREAKING).

  9. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-elon-musk · session_016WV4czSnPb3bu4Q5weHEpr
    os-dev-report (addendum: S2 of delta re-review 6679925198)

    {
     "issue": 30771,
     "status": "done",
     "addendum_to": "6678862496",
     "branch": "claude/project-thread-5uh3yy",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/30849",
     "head": "1764b50e84",
     "session": "session_016WV4czSnPb3bu4Q5weHEpr",
     "dogfood_battery": "1764b50e84 · `bash scripts/pm/os-verify-lock.sh -c 'pnpm --filter @objectstack/dogfood test'` · VERDICT command-exit 0 · held the lock 1511s (25m11s), waited 0s · Test Files 423 passed, 3 skipped (426) · Tests 3534 passed, 41 skipped (3575) · no failures; one test more than on 64f9d94a (3533), the new CONTROL case in mcp-system-object-action-exposure.dogfood.test.ts",
     "ci": "run 42181698191 attempt 1: Test Core (4/8) red on an unrelated cli census timeout (released-port-production-spawn.pin.test.ts, 5000 ms), judged on PR comments 6680122417 / 6680143848; the seat re-ran the failed jobs once, attempt 2 pending at this report",
     "api_writes": "4 this session — relay pr_create, os-dev-report 6678862496, PR comment 6680122417, this addendum",
     "mcp_calls": "1 more since the report — get_job_logs job 127773170008 (read)",
     "open_questions": [],
     "security_findings": "none"
    }

    Generated by Claude Code

  10. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-elon-musk · session_016WV4czvZykUqhYxYXSSDt4

    Landing record · 2026-11-06T17:54Z · PR #30849 merged through the queue as 7569fb57fa on head 15a33791d0. Before that: the seat's ACCEPT, contract review PASS 6679092098 and delta PASS 6679925198 on 1764b50e, and the maintainer's BREAKING word 6687900960. The later delta is test-only (seat note 6690241391). The 15 platform-admin actions now declare requiredPermissions. MCP list_actions leaves them out for a caller without the capability, and REST and MCP run_action refuse it with 403 PERMISSION_DENIED. Card closed completed by Fixes; pm:dispatched removed in this stroke.

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

Metadata

Metadata

Assignees

Labels

domain:serverDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions