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
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
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 变更抽屉显示它。
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/_draftsupdatedBy 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
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.
Studio's changes drawer and properties source line render it, for example 「由 MCP 客户端 代表 作为草稿加入」, in all locales.
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).
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
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.
Activity
objectstack-fleet commentedon Oct 28, 2026
Claim: cloud seat 2, PM loop round 12 · 2026-10-28T09:25Z · p3, S–M · routed
domain:cloudby involvement (pm-dispatch PR #26972) ·pm:queue→pm:dispatchedSession:
session_0123kRqqdpAJWYMgsgdAJX4GAccount:
os-zhuangBranch: the cloud#3302 card thread's own
claude/project-thread-*branch on objectstack, reported here when the PR opensSeat:
repo:cloud#2Premise: holds. Read at objectstack
mainat 2026-10-28T09:22Z:MetadataAuthoringSurfaceSchemais['copilot', 'studio', 'api'](protocol.zod.ts:490).performedByClientIdexists on the execution context and is not recorded indraftChanges.File surface:
packages/spec/src/api/protocol.zod.ts(surface anddraftChangesentry), the metadata service's draft save, Studio's changes drawer and source line inui/**with i18n, generated artifacts, changesetsGoverned: 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
os-zhuang commentedon Oct 28, 2026
PR: #27220 (draft, branch
claude/project-thread-e4rirs), labelledneeds:contract-review.MetadataAuthoringSurfaceSchemagainsmcp.MetadataAuthoringClientSchema{ id, name? }.clienton thedraftChangesentry and on the save request. Both are in-process only and accepted only withsurface: 'mcp'; any other combination is refused400 INVALID_REQUEST.?surface=mcpthe way they refusecopilot.Declarations:
Clause-②: yes (widening)/Metadata-protocol: added.The cloud half, passing
surface: 'mcp'plus the verified client frommcpPrincipal, follows once the pin carries this.Generated by Claude Code