Skip to content

test(authz): e2e-prove the MCP HTTP surface is identity-admitted; upgrade the matrix row to high-risk (#3167)#3225

Merged
os-zhuang merged 1 commit into
mainfrom
claude/adr-0096-mcp-dev-wiring
Jul 18, 2026
Merged

test(authz): e2e-prove the MCP HTTP surface is identity-admitted; upgrade the matrix row to high-risk (#3167)#3225
os-zhuang merged 1 commit into
mainfrom
claude/adr-0096-mcp-dev-wiring

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

#3167PR-B。实现过程中前提再次变化——而且这次是个好消息:接线早已存在

关键发现:决策 A/B/C 早已 ship

serve.tsisMcpServerEnabled() 为真时 requires.push('mcp'),与 dispatcher /mcp 路由同一决策点自动加载 MCPServerPlugin;os dev spawn os serve --dev 继承之;stdio 仍 opt-in。也就是说我们"批准"的三个决策——dev 默认开、仅 HTTP、off-switch 统一——平台早就实现了(甚至 serve/prod 也默认开,因为准入已强制所以安全)。我 #3167 里"从未接线"的判断是过时误读(当初 grep 了不存在的 packages/tools/cli,实际在 packages/cli)。已在 #3167 更新说明。

所以 PR-B 唯一真正缺的,是 mcp-http-identity 行(#3202)明确延后的那块——端到端证明

本 PR:补上端到端证明 + 升级矩阵行

showcase-mcp-http-identity.dogfood.test.ts 启动真实 showcase + 安全栈 + MCPServerPlugin,经真实 HTTP + RLS 栈驱动 POST /api/v1/mcp:

  1. 匿名 tools/call → 401(任何工具执行之前 fail-closed);
  2. 成员的 query_records over owner-private showcase_private_note → 只返回自己的行,两个成员对称——若工具跑在无 scope/system(即 stdio 姿态)下,另一 owner 的行就会泄漏,所以这是 RLS-穿透-MCP 的承重断言;
  3. tool discovery(tools/list)同样受已准入身份门控。

mcp-http-identity 行升级为 HIGH_RISK + proof,关掉 #3202 在该行留的延后注记。dispatcher 层单元覆盖(http-dispatcher.mcp.test.ts 的 401 + EC-传-bridge;.mcp-oauth.test.ts 的 scope 403)本已存在;本 proof 补上单元 mock 无法展示的整栈授权结果

范围与验证

  • 纯测试 + 私有 @objectstack/dogfood 门包加一个 @objectstack/mcp dev-dep;不动运行时、不改任何默认(接线本就在 main 上)→ 无 changeset。
  • 本地:authz-conformance + 新 proof 13/13 绿;checkLedger 校验通过(high-risk 有 proof、proof 文件存在、基线 sound);eslint 干净。

剩余可选项(未纳入本 PR,保持聚焦):dev 启动打印 MCP 连接指引(URL / skill / connect-UI)——纯 DX 补充,值得单独小改。

Refs #3167(PR-B)、ADR-0096、ADR-0056 D10、#3202#2698

🤖 Generated with Claude Code

https://claude.ai/code/session_01Pbmw3pMqNJfPbkvwh9Fkjs


Generated by Claude Code

…rade the matrix row to high-risk (#3167)

PR-B of #3167. During implementation the premise shifted: the CLI ALREADY
auto-loads MCPServerPlugin in `os serve`/`dev` when isMcpServerEnabled()
(serve.ts — requires.push('mcp')), on the SAME decision point that gates the
dispatcher /mcp route, with stdio staying opt-in. So decisions A/B/C (dev
default-on, HTTP-only, unified off-switch) were already shipped — my #3167
"wired nowhere" claim was a stale read (a grep of the wrong path). The one
genuinely-missing piece was the end-to-end proof the mcp-http-identity row
(#3202) explicitly deferred.

This lands that proof: showcase-mcp-http-identity.dogfood.test.ts boots the
real showcase + security + MCPServerPlugin and drives POST /api/v1/mcp through
the real HTTP + RLS stack:
- an anonymous MCP tools/call is 401 before any tool runs (fail-closed);
- a member's query_records over the owner-private showcase_private_note returns
  ONLY their own rows, symmetric across two members — if the tool had run
  unscoped/system (the stdio posture, mcp-stdio-authority) the other owner's
  rows would leak, so this is the load-bearing RLS-through-MCP assertion;
- tool discovery (tools/list) is gated on the same admitted identity.

The mcp-http-identity matrix row is upgraded to HIGH_RISK with this proof,
closing the deferral noted on it in #3202. Dispatcher-level unit coverage
(http-dispatcher.mcp.test.ts 401 + EC-to-bridge; .mcp-oauth.test.ts scope 403)
already existed; this adds the whole-stack authorization outcome the unit
mocks cannot show.

Test-only + a dev-dep on @objectstack/mcp in the private @objectstack/dogfood
gate — no runtime change, no changeset. authz-conformance + the new proof:
13/13 green locally.

Refs #3167, ADR-0096, ADR-0056 D10, #3202, #2698.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pbmw3pMqNJfPbkvwh9Fkjs
@vercel

vercel Bot commented Jul 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Building Building Preview, Comment Jul 18, 2026 3:08pm

Request Review

@github-actions github-actions Bot added size/m dependencies Pull requests that update a dependency file tests labels Jul 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): packages/qa.

2 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/permissions/authorization.mdx (via packages/qa)
  • content/docs/permissions/delegated-administration.mdx (via packages/qa)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review July 18, 2026 15:15
@os-zhuang
os-zhuang merged commit 5d62496 into main Jul 18, 2026
17 of 18 checks passed
@os-zhuang
os-zhuang deleted the claude/adr-0096-mcp-dev-wiring branch July 18, 2026 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file size/m tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants