Skip to content

spec/metadata-protocol: a draft change written through the MCP build door is recorded as by: 'copilot'; draftChanges cannot say "an MCP agent (OAuth client X) on behalf of user Y" (cloud#3302 item 5) #27176

Closed

Description

@objectstack-fleet

Filing gate: ① a product defect with a named location. cloud#3302 item 5 (maintainer-directed, the 2026-10-27 MCP build batch) is not met because of a missing value in MetadataAuthoringSurfaceSchema (packages/spec/src/api/protocol.zod.ts:490).

维护者速读

cloud 的 MCP build 入口(cloud#3302 / cloud#3345)让开发者自己的 agent 通过 /api/v1/mcp 写草稿,由人在 Studio「变更」里发布。卡片第 5 项要求发布的人能看到「哪个入口、哪个 OAuth 客户端、代表谁」写了这条草稿。框架现在的草稿逐键来源 draftChanges(#24298)只有 copilot / studio / api 三种来源和 actor,MCP 写入只能记成 copilot,没有客户端。本卡补上来源值和客户端归属,并让 Studio 变更抽屉显示它。

Facts (objectstack main, read 2026-10-28)

  • MetadataAuthoringSurfaceSchema = z.enum(['copilot', 'studio', 'api']) is at protocol.zod.ts:490. draftChanges[].by is that enum, and actor is the acting user (metadata-protocol / spec: a draft carries no per-field provenance (which surface changed which key, and when), so Studio cannot mark a copilot's draft change with the ruled 草稿 chip and 来源 line #24298).
  • copilot is stated only by an in-process AI tool calling the save, never by a remote caller (protocol.zod.ts:~1000). The cloud MCP door's tools are in-process AI tools, so their saves record by: 'copilot'. That is indistinguishable from the in-app chat.
  • The execution context already carries the OAuth performer for the /mcp door: performedByClientId (ADR-0090 D10 rule 4, kernel/execution-context.zod.ts:298-315). It is attribution only, and it is recorded in sys_audit_log, but not in draftChanges.
  • cloud side (cloud#3345): /meta/_drafts updatedBy is the token user, which is asserted. The tool context carries authoringDoor: 'mcp' and mcpPrincipal { userId, clientId, organizationId }, ready to pass into the save.

Done looks like

  1. The draft save can record, in-process only, that a change came through the MCP door and which OAuth client performed it: a new surface value (for example mcp) and an optional client attribution on the draftChanges entry. The exact shape is the spec owner's call. It stays refused from ?surface= over HTTP, the way copilot is.
  2. Studio's changes drawer and properties source line render it, for example 「由 MCP 客户端 代表 作为草稿加入」, in all locales.
  3. A follow-up cloud half (cloud#3302 stays open, Blocked-by: this card) passes surface and the client from the MCP door's tool context into saveMetaItem.

Out of scope

Who may write through the door (cloud#3299 and #3303), and any change to authorization. This card is attribution only.

Dedup: #24298 (closed; the per-key provenance this extends), #26587 (closed; consent copy for metadata:write). There is no open card on draft attribution for MCP.

Reader: the spec/metadata-protocol lane plus Studio (ui). Routed domain:cloud by involvement (pm-dispatch #26972).

Activity

  1. added
    enhancementNew feature or request
    domain:cloudCloud-service journey parked for the cloud PM to migrate — not dispatched in this repo (云服务旅程,本仓不派)
    and removed on Oct 28, 2026
  2. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: cloud seat 2, PM loop round 12 · 2026-10-28T09:25Z · p3, S–M · routed domain:cloud by involvement (pm-dispatch PR #26972) · pm:queue → pm:dispatched
    Session: session_0123kRqqdpAJWYMgsgdAJX4G
    Account: os-zhuang
    Branch: the cloud#3302 card thread's own claude/project-thread-* branch on objectstack, reported here when the PR opens
    Seat: repo:cloud#2
    Premise: holds. Read at objectstack main at 2026-10-28T09:22Z:

    • MetadataAuthoringSurfaceSchema is ['copilot', 'studio', 'api'] (protocol.zod.ts:490).
    • performedByClientId exists on the execution context and is not recorded in draftChanges.
      File surface: packages/spec/src/api/protocol.zod.ts (surface and draftChanges entry), the metadata service's draft save, Studio's changes drawer and source line in ui/** with i18n, generated artifacts, changesets
      Governed: re-checked on the final file list. This is a published-schema face, so it gets a contract review (CONTRACT_REVIEW_TIER) by an agent other than the drafter.
      Clause-②: yes (widening), expected
      Metadata-protocol: added, expected

    Generated by Claude Code

  3. os-zhuang commented on Oct 28, 2026

    @os-zhuang
    Contributor

    PR: #27220 (draft, branch claude/project-thread-e4rirs), labelled needs:contract-review.

    • MetadataAuthoringSurfaceSchema gains mcp.
    • New MetadataAuthoringClientSchema { id, name? }.
    • An optional client on the draftChanges entry and on the save request. Both are in-process only and accepted only with surface: 'mcp'; any other combination is refused 400 INVALID_REQUEST.
    • The HTTP doors refuse ?surface=mcp the way they refuse copilot.
    • Studio's properties source line and the changes drawer render the surface and client. The drawer covers all ten locales; the designer table covers en and zh.

    Declarations: Clause-②: yes (widening) / Metadata-protocol: added.

    The cloud half, passing surface: 'mcp' plus the verified client from mcpPrincipal, follows once the pin carries this.


    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

Labels

domain:cloudCloud-service journey parked for the cloud PM to migrate — not dispatched in this repo (云服务旅程,本仓不派)enhancementNew feature or requestpm:dispatchedpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions